Mercurial > public > cpp-enigma
comparison enigma/tests/test_rotor.t.h @ 2:713fa2a9ea9a
CxxTest support. Added rotor tests.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Fri, 22 Jun 2012 22:02:55 -0500 |
parents | |
children | f4e25e6b76c3 |
comparison
equal
deleted
inserted
replaced
1:1459e74fda3f | 2:713fa2a9ea9a |
---|---|
1 // Copyright (C) 2012 by Brian Neal. | |
2 // This file is part of Cpp-Enigma, the Enigma Machine simulation. | |
3 // Cpp-Enigma is released under the MIT License (see License.txt). | |
4 // | |
5 // test_rotor.t.h - rotor unit tests | |
6 | |
7 #include <deque> | |
8 #include <string> | |
9 #include <memory> | |
10 #include <cxxtest/TestSuite.h> | |
11 #include "rotor.h" | |
12 #include "enigma_utils.h" | |
13 #include "rotor_data.h" | |
14 #include "rotor_factory.h" | |
15 | |
16 using namespace enigma; | |
17 | |
18 const char* const wiring = "EKMFLGDQVZNTOWYHXUSPAIBRCJ"; | |
19 | |
20 | |
21 class MyTestSuite1 : public CxxTest::TestSuite | |
22 { | |
23 public: | |
24 | |
25 void test_bad_wiring() | |
26 { | |
27 TS_ASSERT_THROWS(rotor("I", ""), rotor_error); | |
28 TS_ASSERT_THROWS(rotor("I", "ABC"), rotor_error); | |
29 TS_ASSERT_THROWS(rotor("I", "123"), rotor_error); | |
30 TS_ASSERT_THROWS(rotor("I", "!\"#$%&'()*+,-./:;<=>?@[\\]^"), rotor_error); | |
31 TS_ASSERT_THROWS(rotor("I", "ABCDABCDABCDABCDABCDABCDAB"), rotor_error); | |
32 } | |
33 | |
34 void test_bad_ring_setting() | |
35 { | |
36 TS_ASSERT_THROWS(rotor("I", wiring, -1), rotor_error); | |
37 TS_ASSERT_THROWS(rotor("I", wiring, 26), rotor_error); | |
38 } | |
39 | |
40 void test_bad_stepping() | |
41 { | |
42 TS_ASSERT_THROWS(rotor("I", wiring, 1, "0"), rotor_error); | |
43 TS_ASSERT_THROWS(rotor("I", wiring, 1, "-"), rotor_error); | |
44 TS_ASSERT_THROWS(rotor("I", wiring, 1, "A%"), rotor_error); | |
45 TS_ASSERT_THROWS(rotor("I", wiring, 1, "A%14"), rotor_error); | |
46 } | |
47 | |
48 void test_display() | |
49 { | |
50 for (int i = 0; i < 26; ++i) | |
51 { | |
52 rotor r{"I", wiring, i}; | |
53 for (int j = 0; j < 26; ++j) | |
54 { | |
55 r.set_display(j + 'A'); | |
56 TS_ASSERT_EQUALS(j + 'A', r.get_display()); | |
57 } | |
58 } | |
59 } | |
60 | |
61 // Loop through all ring settings & rotor positions and test the wiring. | |
62 void test_wiring() | |
63 { | |
64 for (int r = 0; r < 26; ++r) | |
65 { | |
66 rotor test_rotor("I", wiring, r); | |
67 | |
68 for (int n = 0; n < 26; ++n) | |
69 { | |
70 const char d = n + 'A'; | |
71 test_rotor.set_display(d); | |
72 | |
73 std::deque<char> wiring_deque(wiring, wiring + 26); | |
74 // rotate contents to the right if positive, left if negative: | |
75 int rotate_count = r - n; | |
76 const bool rotate_right = rotate_count >= 0; | |
77 if (rotate_count < 0) | |
78 { | |
79 rotate_count = -rotate_count; | |
80 } | |
81 for (int x = 0; x < rotate_count; ++x) | |
82 { | |
83 if (rotate_right) | |
84 { | |
85 wiring_deque.push_front(wiring_deque.back()); | |
86 wiring_deque.pop_back(); | |
87 } | |
88 else | |
89 { | |
90 wiring_deque.push_back(wiring_deque.front()); | |
91 wiring_deque.pop_front(); | |
92 } | |
93 } | |
94 | |
95 for (int i = 0; i < 26; ++i) | |
96 { | |
97 int output = test_rotor.signal_in(i); | |
98 int expected = alpha_mod(wiring_deque[i] - 'A' + r - n); | |
99 TS_ASSERT_EQUALS(output, expected); | |
100 | |
101 output = test_rotor.signal_out(expected); | |
102 TS_ASSERT_EQUALS(output, i); | |
103 } | |
104 } | |
105 } | |
106 } | |
107 | |
108 // For every rotor we simulate, ensure that the notch setting is correct | |
109 // regardless of the ring setting. | |
110 void test_notches() | |
111 { | |
112 for (const auto& p : simulated_rotors) | |
113 { | |
114 const std::string& rotor_name(p.first); | |
115 const rotor_data& rd(p.second); | |
116 if (rd.stepping == nullptr) | |
117 { | |
118 continue; | |
119 } | |
120 const std::string notches(rd.stepping); | |
121 | |
122 for (int r = 0; r < 26; ++r) | |
123 { | |
124 std::unique_ptr<rotor> rp = create_rotor(rotor_name.c_str(), r); | |
125 rp->set_display('A'); | |
126 | |
127 for (int n = 0; n < 26; ++n) | |
128 { | |
129 const bool over_notch = notches.find(rp->get_display()) != std::string::npos; | |
130 TS_ASSERT_EQUALS(over_notch, rp->notch_over_pawl()); | |
131 } | |
132 } | |
133 } | |
134 } | |
135 | |
136 void test_rotate() | |
137 { | |
138 for (int r = 0; r < 26; ++r) | |
139 { | |
140 rotor r1("X", wiring, r); | |
141 rotor r2("Y", wiring, r); | |
142 | |
143 r2.set_display('A'); | |
144 for (int i = 0; i < 26; ++i) | |
145 { | |
146 r1.set_display(i + 'A'); | |
147 TS_ASSERT_EQUALS(r1.get_display(), r2.get_display()); | |
148 r2.rotate(); | |
149 } | |
150 } | |
151 } | |
152 | |
153 void test_ring_setting() | |
154 { | |
155 rotor r("X", wiring, 0); | |
156 for (int n = 0; n < 26; ++n) | |
157 { | |
158 r.set_ring_setting(n); | |
159 TS_ASSERT_EQUALS(n, r.get_ring_setting()); | |
160 | |
161 r.set_display('A'); | |
162 for (int a = 0; a < 26; ++a) | |
163 { | |
164 TS_ASSERT_EQUALS(a + 'A', r.get_display()); | |
165 r.rotate(); | |
166 } | |
167 } | |
168 } | |
169 }; |