annotate enigma/tests/test_machine.t.h @ 7:db1216d380b3

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