diff options
| author | J08nY | 2018-12-11 21:24:35 +0100 |
|---|---|---|
| committer | J08nY | 2019-03-21 11:00:14 +0100 |
| commit | 0c740f412626f33f08d6bb9857f0c5619b9ea79c (patch) | |
| tree | c2313faaf8bc878d3d72acf2fd7c830b9512a529 /test/sca | |
| parent | cbeca585d5787e8cab35fb5207339e7b22eab382 (diff) | |
| download | pyecsca-0c740f412626f33f08d6bb9857f0c5619b9ea79c.tar.gz pyecsca-0c740f412626f33f08d6bb9857f0c5619b9ea79c.tar.zst pyecsca-0c740f412626f33f08d6bb9857f0c5619b9ea79c.zip | |
Move SCA stuff to sca package.
Diffstat (limited to 'test/sca')
| -rw-r--r-- | test/sca/__init__.py | 0 | ||||
| -rw-r--r-- | test/sca/test_align.py | 76 | ||||
| -rw-r--r-- | test/sca/test_combine.py | 35 | ||||
| -rw-r--r-- | test/sca/test_edit.py | 28 | ||||
| -rw-r--r-- | test/sca/test_filter.py | 35 | ||||
| -rw-r--r-- | test/sca/test_process.py | 50 | ||||
| -rw-r--r-- | test/sca/test_sampling.py | 37 | ||||
| -rw-r--r-- | test/sca/test_trace.py | 12 | ||||
| -rw-r--r-- | test/sca/test_traceset.py | 58 | ||||
| -rw-r--r-- | test/sca/test_ttest.py | 25 | ||||
| -rw-r--r-- | test/sca/utils.py | 24 |
11 files changed, 380 insertions, 0 deletions
diff --git a/test/sca/__init__.py b/test/sca/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/sca/__init__.py diff --git a/test/sca/test_align.py b/test/sca/test_align.py new file mode 100644 index 0000000..3e64334 --- /dev/null +++ b/test/sca/test_align.py @@ -0,0 +1,76 @@ +from unittest import TestCase + +import numpy as np +from pyecsca.sca import align_correlation, align_peaks, align_sad, align_dtw_scale,\ + align_dtw, Trace, InspectorTraceSet +from .utils import slow, plot + + +class AlignTests(TestCase): + + def test_align(self): + first_arr = np.array([10, 64, 120, 64, 10, 10, 10, 10, 10], dtype=np.dtype("i1")) + second_arr = np.array([10, 10, 10, 10, 50, 80, 50, 20, 10], dtype=np.dtype("i1")) + third_arr = np.array([70, 30, 42, 35, 28, 21, 15, 10, 5], dtype=np.dtype("i1")) + a = Trace(None, None, first_arr) + b = Trace(None, None, second_arr) + c = Trace(None, None, third_arr) + result = align_correlation(a, b, c, reference_offset=1, reference_length=3, max_offset=4, min_correlation=0.65) + self.assertIsNotNone(result) + self.assertEqual(len(result), 2) + np.testing.assert_equal(result[0].samples, first_arr) + np.testing.assert_equal(result[1].samples, np.array([10, 50, 80, 50, 20, 10, 0, 0, 0], dtype=np.dtype("i1"))) + + @slow + def test_large_align(self): + example = InspectorTraceSet("test/data/example.trs") + result = align_correlation(*example, reference_offset=100000, reference_length=20000, max_offset=15000) + self.assertIsNotNone(result) + + @slow + def test_large_dtw_align(self): + example = InspectorTraceSet("test/data/example.trs") + result = align_dtw(*example[:5]) + self.assertIsNotNone(result) + + def test_peak_align(self): + first_arr = np.array([10, 64, 14, 120, 15, 30, 10, 15, 20, 15, 15, 10, 10], dtype=np.dtype("i1")) + second_arr = np.array([10, 10, 10, 10, 90, 40, 50, 20, 10, 17, 16, 10, 10], dtype=np.dtype("i1")) + a = Trace(None, None, first_arr) + b = Trace(None, None, second_arr) + result = align_peaks(a, b, reference_offset=2, reference_length=5, max_offset=3) + self.assertEqual(np.argmax(result[0].samples), np.argmax(result[1].samples)) + + def test_sad_align(self): + first_arr = np.array([10, 64, 14, 120, 15, 30, 10, 15, 20, 15, 15, 10, 10], dtype=np.dtype("i1")) + second_arr = np.array([10, 10, 10, 10, 90, 40, 50, 20, 10, 17, 16, 10, 10], dtype=np.dtype("i1")) + a = Trace(None, None, first_arr) + b = Trace(None, None, second_arr) + result = align_sad(a, b, reference_offset=2, reference_length=5, max_offset=3) + self.assertEqual(len(result), 2) + + def test_dtw_align_scale(self): + first_arr = np.array([10, 64, 14, 120, 15, 30, 10, 15, 20, 15, 15, 10, 10, 8, 10, 12, 10, 13, 9], dtype=np.dtype("i1")) + second_arr = np.array([10, 10, 10, 10, 60, 40, 90, 20, 10, 17, 16, 10, 10, 10, 10, 10, 17, 12, 10], dtype=np.dtype("i1")) + third_arr = np.array([10, 30, 20, 21, 15, 8, 10, 37, 21, 77, 20, 28, 25, 10, 9, 10, 15, 9, 10], dtype=np.dtype("i1")) + a = Trace(None, None, first_arr) + b = Trace(None, None, second_arr) + c = Trace(None, None, third_arr) + result = align_dtw_scale(a, b, c) + + self.assertEqual(np.argmax(result[0].samples), np.argmax(result[1].samples)) + self.assertEqual(np.argmax(result[1].samples), np.argmax(result[2].samples)) + plot(self, *result) + + def test_dtw_align(self): + first_arr = np.array([10, 64, 14, 120, 15, 30, 10, 15, 20, 15, 15, 10, 10, 8, 10, 12, 10, 13, 9], dtype=np.dtype("i1")) + second_arr = np.array([10, 10, 10, 10, 60, 40, 90, 20, 10, 17, 16, 10, 10, 10, 10, 10, 17, 12, 10], dtype=np.dtype("i1")) + third_arr = np.array([10, 30, 20, 21, 15, 8, 10, 47, 21, 77, 20, 28, 25, 10, 9, 10, 15, 9, 10], dtype=np.dtype("i1")) + a = Trace(None, None, first_arr) + b = Trace(None, None, second_arr) + c = Trace(None, None, third_arr) + result = align_dtw(a, b, c) + + self.assertEqual(np.argmax(result[0].samples), np.argmax(result[1].samples)) + self.assertEqual(np.argmax(result[1].samples), np.argmax(result[2].samples)) + plot(self, *result) diff --git a/test/sca/test_combine.py b/test/sca/test_combine.py new file mode 100644 index 0000000..113eb69 --- /dev/null +++ b/test/sca/test_combine.py @@ -0,0 +1,35 @@ +from unittest import TestCase + +import numpy as np +from pyecsca.sca import Trace, CombinedTrace, average, conditional_average, standard_deviation + + +class CombineTests(TestCase): + + def setUp(self): + self.a = Trace(None, b"\xff", np.array([20, 80], dtype=np.dtype("i1"))) + self.b = Trace(None, b"\xff", np.array([30, 42], dtype=np.dtype("i1"))) + self.c = Trace(None, b"\x00", np.array([78, 56], dtype=np.dtype("i1"))) + + def test_average(self): + self.assertIsNone(average()) + result = average(self.a, self.b) + self.assertIsNotNone(result) + self.assertIsInstance(result, CombinedTrace) + self.assertEqual(len(result.samples), 2) + self.assertEqual(result.samples[0], 25) + self.assertEqual(result.samples[1], 61) + + def test_conditional_average(self): + result = conditional_average(self.a, self.b, self.c, + condition=lambda trace: trace.data[0] == 0xff) + self.assertIsInstance(result, CombinedTrace) + self.assertEqual(len(result.samples), 2) + self.assertEqual(result.samples[0], 25) + self.assertEqual(result.samples[1], 61) + + def test_standard_deviation(self): + self.assertIsNone(standard_deviation()) + result = standard_deviation(self.a, self.b) + self.assertIsInstance(result, CombinedTrace) + self.assertEqual(len(result.samples), 2) diff --git a/test/sca/test_edit.py b/test/sca/test_edit.py new file mode 100644 index 0000000..88376aa --- /dev/null +++ b/test/sca/test_edit.py @@ -0,0 +1,28 @@ +from unittest import TestCase + +import numpy as np + +from pyecsca.sca import Trace, trim, reverse, pad + + +class EditTests(TestCase): + + def setUp(self): + self._trace = Trace(None, None, np.array([10, 20, 30, 40, 50], dtype=np.dtype("i1"))) + + def test_trim(self): + result = trim(self._trace, 2) + self.assertIsNotNone(result) + np.testing.assert_equal(result.samples, np.array([30, 40, 50], dtype=np.dtype("i1"))) + + def test_reverse(self): + result = reverse(self._trace) + self.assertIsNotNone(result) + np.testing.assert_equal(result.samples, + np.array([50, 40, 30, 20, 10], dtype=np.dtype("i1"))) + + def test_pad(self): + result = pad(self._trace, 2) + self.assertIsNotNone(result) + np.testing.assert_equal(result.samples, + np.array([0, 0, 10, 20, 30, 40, 50, 0, 0], dtype=np.dtype("i1"))) diff --git a/test/sca/test_filter.py b/test/sca/test_filter.py new file mode 100644 index 0000000..c95d5b5 --- /dev/null +++ b/test/sca/test_filter.py @@ -0,0 +1,35 @@ +from unittest import TestCase + +import numpy as np +from pyecsca.sca import Trace, filter_lowpass, filter_highpass, filter_bandpass, filter_bandstop +from .utils import plot + + +class FilterTests(TestCase): + + def setUp(self): + self._trace = Trace(None, None, np.array([5, 12, 15, 13, 15, 11, 7, 2, -4, -8, -10, -8, -13, -9, -11, -8, -5], dtype=np.dtype("i1"))) + + def test_lowpass(self): + result = filter_lowpass(self._trace, 100, 20) + self.assertIsNotNone(result) + self.assertEqual(len(self._trace.samples), len(result.samples)) + plot(self, self._trace, result) + + def test_highpass(self): + result = filter_highpass(self._trace, 128, 20) + self.assertIsNotNone(result) + self.assertEqual(len(self._trace.samples), len(result.samples)) + plot(self, self._trace, result) + + def test_bandpass(self): + result = filter_bandpass(self._trace, 128, 20, 60) + self.assertIsNotNone(result) + self.assertEqual(len(self._trace.samples), len(result.samples)) + plot(self, self._trace, result) + + def test_bandstop(self): + result = filter_bandstop(self._trace, 128, 20, 60) + self.assertIsNotNone(result) + self.assertEqual(len(self._trace.samples), len(result.samples)) + plot(self, self._trace, result) diff --git a/test/sca/test_process.py b/test/sca/test_process.py new file mode 100644 index 0000000..5b80d1f --- /dev/null +++ b/test/sca/test_process.py @@ -0,0 +1,50 @@ +from unittest import TestCase + +import numpy as np +from pyecsca.sca import Trace, absolute, invert, threshold, rolling_mean, offset, recenter, normalize, normalize_wl + + +class ProcessTests(TestCase): + + def setUp(self): + self._trace = Trace(None, None, np.array([30, -60, 145, 247], dtype=np.dtype("i2"))) + + def test_absolute(self): + result = absolute(self._trace) + self.assertIsNotNone(result) + self.assertEqual(result.samples[1], 60) + + def test_invert(self): + result = invert(self._trace) + self.assertIsNotNone(result) + np.testing.assert_equal(result.samples, [-30, 60, -145, -247]) + + def test_threshold(self): + result = threshold(self._trace, 128) + self.assertIsNotNone(result) + self.assertEqual(result.samples[0], 0) + self.assertEqual(result.samples[2], 1) + + def test_rolling_mean(self): + result = rolling_mean(self._trace, 2) + self.assertIsNotNone(result) + self.assertEqual(len(result.samples), 3) + self.assertEqual(result.samples[0], -15) + self.assertEqual(result.samples[1], 42) + self.assertEqual(result.samples[2], 196) + + def test_offset(self): + result = offset(self._trace, 5) + self.assertIsNotNone(result) + np.testing.assert_equal(result.samples, np.array([35, -55, 150, 252], dtype=np.dtype("i2"))) + + def test_recenter(self): + self.assertIsNotNone(recenter(self._trace)) + + def test_normalize(self): + result = normalize(self._trace) + self.assertIsNotNone(result) + + def test_normalize_wl(self): + result = normalize_wl(self._trace) + self.assertIsNotNone(result)
\ No newline at end of file diff --git a/test/sca/test_sampling.py b/test/sca/test_sampling.py new file mode 100644 index 0000000..75a227d --- /dev/null +++ b/test/sca/test_sampling.py @@ -0,0 +1,37 @@ +from unittest import TestCase + +import numpy as np +from pyecsca.sca import Trace, downsample_average, downsample_pick, downsample_decimate +from .utils import plot + + +class SamplingTests(TestCase): + + def setUp(self): + self._trace = Trace(None, None, np.array([20, 40, 50, 50, 10], dtype=np.dtype("i1"))) + + def test_downsample_average(self): + result = downsample_average(self._trace, 2) + self.assertIsNotNone(result) + self.assertIsInstance(result, Trace) + self.assertEqual(len(result.samples), 2) + self.assertEqual(result.samples[0], 30) + self.assertEqual(result.samples[1], 50) + + def test_downsample_pick(self): + result = downsample_pick(self._trace, 2) + self.assertIsNotNone(result) + self.assertIsInstance(result, Trace) + self.assertEqual(len(result.samples), 3) + self.assertEqual(result.samples[0], 20) + self.assertEqual(result.samples[1], 50) + + def test_downsample_decimate(self): + trace = Trace(None, None, np.array([20, 30, 55, 18, 15, 10, 35, 24, 21, 15, 10, 8, -10, -5, + -8, -12, -15, -18, -34, -21, -17, -10, -5, -12, -6, -2, + 4, 8, 21, 28], dtype=np.dtype("i1"))) + result = downsample_decimate(trace, 2) + self.assertIsNotNone(result) + self.assertIsInstance(result, Trace) + self.assertEqual(len(result.samples), 15) + plot(self, trace, result) diff --git a/test/sca/test_trace.py b/test/sca/test_trace.py new file mode 100644 index 0000000..91b7161 --- /dev/null +++ b/test/sca/test_trace.py @@ -0,0 +1,12 @@ +from unittest import TestCase +import numpy as np +from pyecsca.sca import Trace + + +class TraceTests(TestCase): + + def test_basic(self): + trace = Trace("Name", b"\xff\xaa", np.array([10, 15, 24], dtype=np.dtype("i1"))) + self.assertIsNotNone(trace) + self.assertIn("Trace", str(trace)) + self.assertIsNone(trace.trace_set) diff --git a/test/sca/test_traceset.py b/test/sca/test_traceset.py new file mode 100644 index 0000000..90768c2 --- /dev/null +++ b/test/sca/test_traceset.py @@ -0,0 +1,58 @@ +from unittest import TestCase +import os.path +import tempfile + +from pyecsca.sca import TraceSet, InspectorTraceSet, ChipWhispererTraceSet + + +class TraceSetTests(TestCase): + + def test_create(self): + self.assertIsNotNone(TraceSet()) + self.assertIsNotNone(InspectorTraceSet()) + self.assertIsNotNone(ChipWhispererTraceSet()) + + +class InspectorTraceSetTests(TestCase): + + def test_load_fname(self): + result = InspectorTraceSet("test/data/example.trs") + self.assertIsNotNone(result) + self.assertEqual(result.global_title, "Example trace set") + self.assertEqual(len(result), 10) + self.assertIn("InspectorTraceSet", str(result)) + self.assertIs(result[0].trace_set, result) + self.assertEqual(result.sampling_frequency, 12500000) + + def test_load_file(self): + with open("test/data/example.trs", "rb") as f: + self.assertIsNotNone(InspectorTraceSet(f)) + + def test_load_bytes(self): + with open("test/data/example.trs", "rb") as f: + self.assertIsNotNone(InspectorTraceSet(f.read())) + + def test_get_bytes(self): + self.assertIsNotNone(bytes(InspectorTraceSet("test/data/example.trs"))) + + def test_keep_traces(self): + trace_set = InspectorTraceSet("test/data/example.trs") + self.assertIsNotNone(trace_set.raw) + trace_set = InspectorTraceSet("test/data/example.trs", keep_raw_traces=False) + self.assertIsNone(trace_set.raw) + + def test_save(self): + trace_set = InspectorTraceSet("test/data/example.trs") + with tempfile.TemporaryDirectory() as dirname: + path = os.path.join(dirname, "out.trs") + trace_set.save(path) + self.assertTrue(os.path.exists(path)) + self.assertIsNotNone(InspectorTraceSet(path)) + + +class ChipWhispererTraceSetTest(TestCase): + + def test_load_fname(self): + result = ChipWhispererTraceSet("test/data/", "chipwhisperer") + self.assertIsNotNone(result) + self.assertEqual(len(result), 2) diff --git a/test/sca/test_ttest.py b/test/sca/test_ttest.py new file mode 100644 index 0000000..02f78c5 --- /dev/null +++ b/test/sca/test_ttest.py @@ -0,0 +1,25 @@ +from unittest import TestCase + +import numpy as np +from pyecsca.sca import Trace, welch_ttest, student_ttest + + +class TTestTests(TestCase): + + def setUp(self): + self.a = Trace(None, b"\xff", np.array([20, 80], dtype=np.dtype("i1"))) + self.b = Trace(None, b"\xff", np.array([30, 42], dtype=np.dtype("i1"))) + self.c = Trace(None, b"\x00", np.array([78, 56], dtype=np.dtype("i1"))) + self.d = Trace(None, b"\x00", np.array([98, 36], dtype=np.dtype("i1"))) + + def test_welch_ttest(self): + self.assertIsNotNone(welch_ttest([self.a, self.b], [self.c, self.d])) + a = Trace(None, None, np.array([19.8, 20.4, 19.6, 17.8, 18.5, 18.9, 18.3, 18.9, 19.5, 22.0])) + b = Trace(None, None, np.array([28.2, 26.6, 20.1, 23.3, 25.2, 22.1, 17.7, 27.6, 20.6, 13.7])) + c = Trace(None, None, np.array([20.2, 21.6, 27.1, 13.3, 24.2, 20.1, 11.7, 25.6, 26.6, 21.4])) + + result = welch_ttest([a, b], [b, c]) + self.assertIsNotNone(result) + + def test_students_ttest(self): + self.assertIsNotNone(student_ttest([self.a, self.b], [self.c, self.d])) diff --git a/test/sca/utils.py b/test/sca/utils.py new file mode 100644 index 0000000..1083b87 --- /dev/null +++ b/test/sca/utils.py @@ -0,0 +1,24 @@ +import matplotlib.pyplot as plt +from unittest import TestCase +from pyecsca.sca import Trace +from os.path import join, exists +from os import mkdir, getenv + + +def slow(func): + func.slow = 1 + return func + + +def plot(case: TestCase, *traces: Trace): + if getenv("PYECSCA_TEST_PLOTS") is None: + return + fig = plt.figure() + ax = fig.add_subplot(111) + for i, trace in enumerate(traces): + ax.plot(trace.samples, label=str(i)) + ax.legend(loc="best") + directory = join("test", "plots") + if not exists(directory): + mkdir(directory) + plt.savefig(join(directory, case.id() + ".png")) |
