annotate enigma/tests/test_machine.t.h @ 13:b9d124a15926

To improve cache performance, the enigma machine rotors are now stored together with the reflector in a vector.
author Brian Neal <bgneal@gmail.com>
date Mon, 02 Jul 2012 19:14:36 -0500
parents b90a41f0cd94
children 280facb82b80
rev   line source
bgneal@4 1 // Copyright (C) 2012 by Brian Neal.
bgneal@4 2 // This file is part of Cpp-Enigma, the Enigma Machine simulation.
bgneal@4 3 // Cpp-Enigma is released under the MIT License (see License.txt).
bgneal@4 4 //
bgneal@4 5 // test_machine.t.h - Unit tests for the enigma_machine class.
bgneal@4 6
bgneal@4 7 #include <memory>
bgneal@4 8 #include <string>
bgneal@4 9 #include <vector>
bgneal@4 10 #include <cxxtest/TestSuite.h>
bgneal@4 11 #include "machine.h"
bgneal@4 12 #include "enigma_utils.h"
bgneal@4 13
bgneal@4 14 using namespace enigma;
bgneal@4 15
bgneal@4 16
bgneal@7 17 class display_suite : public CxxTest::TestSuite
bgneal@7 18 {
bgneal@7 19 public:
bgneal@7 20
bgneal@7 21 void test_set_display3()
bgneal@7 22 {
bgneal@7 23 enigma_machine m({"II", "IV", "V"}, {}, "B");
bgneal@7 24 TS_ASSERT_THROWS(m.set_display("ABCD"), enigma_machine_error);
bgneal@7 25 TS_ASSERT_THROWS_NOTHING(m.set_display("ABC"));
bgneal@7 26 }
bgneal@7 27
bgneal@7 28 void test_set_display4()
bgneal@7 29 {
bgneal@7 30 enigma_machine m({"Gamma", "II", "IV", "V"}, {}, "B-Thin");
bgneal@7 31 TS_ASSERT_THROWS(m.set_display("BCD"), enigma_machine_error);
bgneal@7 32 TS_ASSERT_THROWS_NOTHING(m.set_display("ABCD"));
bgneal@7 33 }
bgneal@8 34
bgneal@8 35 void test_navy_str()
bgneal@8 36 {
bgneal@8 37 const std::string stecker = "1/20 2/12 4/6 7/10 8/13 14/23 15/16 17/25 18/26 22/24";
bgneal@8 38 enigma_machine machine({"Beta", "II", "IV", "I"}, {0, 0, 0, 21}, "B-Thin", stecker);
bgneal@8 39
bgneal@8 40 TS_ASSERT_EQUALS(machine.navy_str(), "B-Thin Beta/0 II/0 IV/0 I/21 AAAA "
bgneal@8 41 "1/20 2/12 4/6 7/10 8/13 14/23 15/16 17/25 18/26 22/24");
bgneal@8 42 }
bgneal@8 43
bgneal@8 44 void test_army_str()
bgneal@8 45 {
bgneal@8 46 enigma_machine machine({"II", "IV", "V"}, {1, 20, 11}, "B",
bgneal@8 47 "AV BS CG DL FU HZ IN KM OW RX");
bgneal@8 48
bgneal@8 49 TS_ASSERT_EQUALS(machine.army_str(), "B II/1 IV/20 V/11 AAA "
bgneal@8 50 "AV BS CG DL FU HZ IN KM OW RX");
bgneal@8 51 }
bgneal@7 52 };
bgneal@7 53
bgneal@4 54 class stepping_test_suite : public CxxTest::TestSuite
bgneal@4 55 {
bgneal@4 56 public:
bgneal@4 57
bgneal@4 58 void test_double_stepping()
bgneal@4 59 {
bgneal@4 60 // Ensure the rotors step realistically by testing for a "double-step"
bgneal@4 61 // This example taken from
bgneal@4 62 // http://users.telenet.be/d.rijmenants/en/enigmatech.htm
bgneal@4 63 // in the section on "The Stepping Mechanism."
bgneal@4 64
bgneal@4 65 enigma_machine m({"III", "II", "I"}, {});
bgneal@4 66 m.set_display('K', 'D', 'O');
bgneal@4 67
bgneal@4 68 const std::vector<std::string> truth_data = {
bgneal@4 69 "KDP", "KDQ", "KER", "LFS", "LFT", "LFU",
bgneal@4 70 };
bgneal@4 71
bgneal@4 72 for (const auto& expected : truth_data)
bgneal@4 73 {
bgneal@4 74 m.key_press('A');
bgneal@4 75 TS_ASSERT_EQUALS(m.get_display(), expected);
bgneal@4 76 }
bgneal@4 77 }
bgneal@4 78 };
bgneal@4 79
bgneal@4 80
bgneal@4 81 class simple_cipher_test_suite : public CxxTest::TestSuite
bgneal@4 82 {
bgneal@4 83 public:
bgneal@4 84
bgneal@4 85 void setUp()
bgneal@4 86 {
bgneal@4 87 m.reset(new enigma_machine({"I", "II", "III"}, {}));
bgneal@4 88 m->set_display('A', 'A', 'A');
bgneal@4 89 plaintext = "AAAAA";
bgneal@4 90 ciphertext = "BDZGO";
bgneal@4 91 }
bgneal@4 92
bgneal@4 93 void test_simple_encrypt()
bgneal@4 94 {
bgneal@4 95 std::vector<char> buffer(plaintext.size());
bgneal@4 96 m->process_text(plaintext.c_str(), buffer.data(), plaintext.size());
bgneal@4 97 TS_ASSERT_EQUALS(ciphertext, std::string(buffer.begin(), buffer.end()));
bgneal@4 98 }
bgneal@4 99
bgneal@4 100 void test_simple_decrypt()
bgneal@4 101 {
bgneal@4 102 std::vector<char> buffer(plaintext.size());
bgneal@4 103 m->process_text(ciphertext.c_str(), buffer.data(), ciphertext.size());
bgneal@4 104 TS_ASSERT_EQUALS(plaintext, std::string(buffer.begin(), buffer.end()));
bgneal@4 105 }
bgneal@4 106
bgneal@4 107 private:
bgneal@4 108 std::unique_ptr<enigma_machine> m;
bgneal@4 109 std::string plaintext;
bgneal@4 110 std::string ciphertext;
bgneal@4 111 };
bgneal@4 112
bgneal@4 113
bgneal@4 114 // This example taken from Dirk Rijmenants' simulator manual.
bgneal@4 115 //
bgneal@4 116 // It is credited to Frode Weierud and Geoff Sullivan.
bgneal@4 117 // http://cryptocellar.com
bgneal@4 118 //
bgneal@4 119 class actual_decrypt_test_suite : public CxxTest::TestSuite
bgneal@4 120 {
bgneal@4 121 public:
bgneal@4 122 void setUp()
bgneal@4 123 {
bgneal@4 124 m.reset(new enigma_machine({"II", "IV", "V"}, {1, 20, 11}, "B",
bgneal@4 125 "AV BS CG DL FU HZ IN KM OW RX"));
bgneal@4 126 }
bgneal@4 127
bgneal@4 128 void decrypt(const std::string& start,
bgneal@4 129 const std::string& enc_key,
bgneal@4 130 const std::string& ciphertext,
bgneal@4 131 const std::string& truth_data)
bgneal@4 132 {
bgneal@4 133 // remove spaces & Kenngruppen from ciphertext
bgneal@4 134 std::string ctext(ciphertext.begin() + 5, ciphertext.end());
bgneal@4 135 ctext = remove_spaces(ctext);
bgneal@4 136
bgneal@4 137 // remove spaces from truth_data
bgneal@4 138 const std::string expected(remove_spaces(truth_data));
bgneal@4 139
bgneal@4 140 // decrypt message key to get start position
bgneal@4 141 m->set_display(start[0], start[1], start[2]);
bgneal@4 142 std::string key = m->process_text(enc_key);
bgneal@4 143
bgneal@4 144 // decrypt the message with the key
bgneal@4 145 m->set_display(key[0], key[1], key[2]);
bgneal@4 146
bgneal@4 147 const std::string plaintext = m->process_text(ctext);
bgneal@4 148
bgneal@4 149 TS_ASSERT_EQUALS(plaintext, expected);
bgneal@4 150 }
bgneal@4 151
bgneal@4 152 void test_decrpyt_1()
bgneal@4 153 {
bgneal@4 154 const std::string ciphertext =
bgneal@4 155 "RFUGZ EDPUD NRGYS ZRCXN"
bgneal@4 156 "UYTPO MRMBO FKTBZ REZKM"
bgneal@4 157 "LXLVE FGUEY SIOZV EQMIK"
bgneal@4 158 "UBPMM YLKLT TDEIS MDICA"
bgneal@4 159 "GYKUA CTCDO MOHWX MUUIA"
bgneal@4 160 "UBSTS LRNBZ SZWNR FXWFY"
bgneal@4 161 "SSXJZ VIJHI DISHP RKLKA"
bgneal@4 162 "YUPAD TXQSP INQMA TLPIF"
bgneal@4 163 "SVKDA SCTAC DPBOP VHJK";
bgneal@4 164
bgneal@4 165 const std::string truth_data =
bgneal@4 166 "AUFKL XABTE ILUNG XVONX"
bgneal@4 167 "KURTI NOWAX KURTI NOWAX"
bgneal@4 168 "NORDW ESTLX SEBEZ XSEBE"
bgneal@4 169 "ZXUAF FLIEG ERSTR ASZER"
bgneal@4 170 "IQTUN GXDUB ROWKI XDUBR"
bgneal@4 171 "OWKIX OPOTS CHKAX OPOTS"
bgneal@4 172 "CHKAX UMXEI NSAQT DREIN"
bgneal@4 173 "ULLXU HRANG ETRET ENXAN"
bgneal@4 174 "GRIFF XINFX RGTX";
bgneal@4 175
bgneal@4 176 decrypt("WXC", "KCH", ciphertext, truth_data);
bgneal@4 177 }
bgneal@4 178
bgneal@4 179 void test_decrpyt_2()
bgneal@4 180 {
bgneal@4 181 const std::string ciphertext =
bgneal@4 182 "FNJAU SFBWD NJUSE GQOBH"
bgneal@4 183 "KRTAR EEZMW KPPRB XOHDR"
bgneal@4 184 "OEQGB BGTQV PGVKB VVGBI"
bgneal@4 185 "MHUSZ YDAJQ IROAX SSSNR"
bgneal@4 186 "EHYGG RPISE ZBOVM QIEMM"
bgneal@4 187 "ZCYSG QDGRE RVBIL EKXYQ"
bgneal@4 188 "IRGIR QNRDN VRXCY YTNJR";
bgneal@4 189
bgneal@4 190 const std::string truth_data =
bgneal@4 191 "DREIG EHTLA NGSAM ABERS"
bgneal@4 192 "IQERV ORWAE RTSXE INSSI"
bgneal@4 193 "EBENN ULLSE QSXUH RXROE"
bgneal@4 194 "MXEIN SXINF RGTXD REIXA"
bgneal@4 195 "UFFLI EGERS TRASZ EMITA"
bgneal@4 196 "NFANG XEINS SEQSX KMXKM"
bgneal@4 197 "XOSTW XKAME NECXK";
bgneal@4 198
bgneal@4 199 decrypt("CRS", "YPJ", ciphertext, truth_data);
bgneal@4 200 }
bgneal@4 201
bgneal@4 202 private:
bgneal@4 203 std::unique_ptr<enigma_machine> m;
bgneal@4 204 };
bgneal@4 205
bgneal@4 206
bgneal@4 207 // This is the Kriegsmarine example from Dirk Rijmenants' simulator manual.
bgneal@4 208 //
bgneal@4 209 // It is credited to Stefan Krah and the M4 project:
bgneal@4 210 // http://www.bytereef.org/m4_project.html
bgneal@4 211 //
bgneal@4 212 class kriegsmarine_test_suite : public CxxTest::TestSuite
bgneal@4 213 {
bgneal@4 214 public:
bgneal@4 215
bgneal@4 216 void test_decrypt()
bgneal@4 217 {
bgneal@4 218 const std::string stecker = "1/20 2/12 4/6 7/10 8/13 14/23 15/16 17/25 18/26 22/24";
bgneal@4 219
bgneal@4 220 enigma_machine machine({"Beta", "II", "IV", "I"}, {0, 0, 0, 21}, "B-Thin", stecker);
bgneal@4 221
bgneal@4 222 std::string ciphertext = remove_spaces(
bgneal@4 223 "FCLC QRKN NCZW VUSX PNYM INHZ XMQX SFWX WLKJ AHSH NMCO CCAK UQPM KCSM"
bgneal@4 224 "HKSE INJU SBLK IOSX CKUB HMLL XCSJ USRR DVKO HULX WCCB GVLI YXEO AHXR"
bgneal@4 225 "HKKF VDRE WEZL XOBA FGYU JQUK GRTV UKAM EURB VEKS UHHV OYHA BCJW MAKL"
bgneal@4 226 "FKLM YFVN RIZR VVRT KOFD ANJM OLBG FFLE OPRG TFLV RHOW OPBE KVWM UQFM"
bgneal@4 227 "PWPA RMFH AGKX IIBG FCLC QRKM VA");
bgneal@4 228
bgneal@4 229 // remove the message indicators from the message (the first and last 2
bgneal@4 230 // groups of the message -- it appears the last partial group 'VA' should
bgneal@4 231 // be removed also)
bgneal@4 232
bgneal@4 233 ciphertext = std::string(ciphertext.begin() + 8, ciphertext.end() - 10);
bgneal@4 234
bgneal@4 235 machine.set_display('V', 'J', 'N', 'A');
bgneal@4 236 const std::string plaintext = machine.process_text(ciphertext);
bgneal@4 237
bgneal@4 238 const std::string truth_data = remove_spaces(
bgneal@4 239 "VONV ONJL OOKS JHFF TTTE"
bgneal@4 240 "INSE INSD REIZ WOYY QNNS"
bgneal@4 241 "NEUN INHA LTXX BEIA NGRI"
bgneal@4 242 "FFUN TERW ASSE RGED RUEC"
bgneal@4 243 "KTYW ABOS XLET ZTER GEGN"
bgneal@4 244 "ERST ANDN ULAC HTDR EINU"
bgneal@4 245 "LUHR MARQ UANT ONJO TANE"
bgneal@4 246 "UNAC HTSE YHSD REIY ZWOZ"
bgneal@4 247 "WONU LGRA DYAC HTSM YSTO"
bgneal@4 248 "SSEN ACHX EKNS VIER MBFA"
bgneal@4 249 "ELLT YNNN NNNO OOVI ERYS"
bgneal@4 250 "ICHT EINS NULL");
bgneal@4 251
bgneal@4 252 TS_ASSERT_EQUALS(plaintext, truth_data);
bgneal@4 253 }
bgneal@4 254
bgneal@4 255 };