From d7e9bc57fc267b84f3d766c0948159dbb03f96bb Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Fri, 10 Jun 2016 10:41:30 +0100 Subject: [PATCH] Added tests for bombe --- bombe.ipynb | 236 +++++++++++---- bombe.py | 18 ++ test_bombe.py | 792 ++++++++------------------------------------------ 3 files changed, 313 insertions(+), 733 deletions(-) diff --git a/bombe.ipynb b/bombe.ipynb index 59442e4..93e0ccb 100644 --- a/bombe.ipynb +++ b/bombe.ipynb @@ -75,7 +75,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 31, "metadata": { "collapsed": false }, @@ -116,6 +116,7 @@ " self.connections += [Connection([bank_before, bank_after], scrambler)]\n", " \n", " def read_menu(self, menu):\n", + " self.connections = []\n", " for item in menu:\n", " scrambler = Scrambler(self.wheel1_spec, self.wheel2_spec, self.wheel3_spec,\n", " self.reflector_spec,\n", @@ -199,7 +200,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 32, "metadata": { "collapsed": false }, @@ -211,7 +212,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 33, "metadata": { "collapsed": true }, @@ -227,7 +228,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 34, "metadata": { "collapsed": false }, @@ -238,7 +239,7 @@ "'opgndxcrwomnlnecjz'" ] }, - "execution_count": 7, + "execution_count": 34, "metadata": {}, "output_type": "execute_result" } @@ -252,7 +253,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 35, "metadata": { "collapsed": false }, @@ -263,7 +264,7 @@ "'aas'" ] }, - "execution_count": 8, + "execution_count": 35, "metadata": {}, "output_type": "execute_result" } @@ -274,7 +275,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 36, "metadata": { "collapsed": false }, @@ -302,7 +303,7 @@ " MenuIem(before='e', after='z', number=18)]" ] }, - "execution_count": 9, + "execution_count": 36, "metadata": {}, "output_type": "execute_result" } @@ -314,7 +315,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 37, "metadata": { "collapsed": true }, @@ -327,7 +328,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 38, "metadata": { "collapsed": false }, @@ -355,7 +356,7 @@ " MenuIem(before='e', after='z', number=18)]" ] }, - "execution_count": 11, + "execution_count": 38, "metadata": {}, "output_type": "execute_result" } @@ -366,7 +367,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 39, "metadata": { "collapsed": false }, @@ -377,7 +378,7 @@ "'s'" ] }, - "execution_count": 12, + "execution_count": 39, "metadata": {}, "output_type": "execute_result" } @@ -388,7 +389,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 42, "metadata": { "collapsed": false }, @@ -399,7 +400,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 43, "metadata": { "collapsed": false }, @@ -410,7 +411,7 @@ "18" ] }, - "execution_count": 14, + "execution_count": 43, "metadata": {}, "output_type": "execute_result" } @@ -421,7 +422,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 27, "metadata": { "collapsed": false }, @@ -430,6 +431,24 @@ "name": "stdout", "output_type": "stream", "text": [ + "['t', 'o'] aaa\n", + "['h', 'p'] aab\n", + "['i', 'g'] aac\n", + "['s', 'n'] aad\n", + "['i', 'd'] aae\n", + "['s', 'x'] aaf\n", + "['a', 'c'] aag\n", + "['t', 'r'] aah\n", + "['e', 'w'] aai\n", + "['s', 'o'] aaj\n", + "['t', 'm'] aak\n", + "['m', 'n'] aal\n", + "['e', 'l'] aam\n", + "['s', 'n'] aan\n", + "['s', 'e'] aao\n", + "['a', 'c'] aap\n", + "['g', 'j'] aaq\n", + "['e', 'z'] aar\n", "['t', 'o'] aaa\n", "['h', 'p'] aab\n", "['i', 'g'] aac\n", @@ -458,7 +477,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 44, "metadata": { "collapsed": false }, @@ -466,10 +485,54 @@ { "data": { "text/plain": [ - "False" + "'ot:hp:gi:ns:di:sx:ac:rt:ew:os:mt:mn:el:ns:es:ac:gj:ez'" ] }, - "execution_count": 16, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "':'.join(cat(sorted(c.banks)) for c in bombe.connections)" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "'aaa:aab:aac:aad:aae:aaf:aag:aah:aai:aaj:aak:aal:aam:aan:aao:aap:aaq:aar'" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "':'.join(cat(c.scrambler.wheel_positions_l) for c in bombe.connections)" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 56, "metadata": {}, "output_type": "execute_result" } @@ -480,7 +543,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 57, "metadata": { "collapsed": false }, @@ -488,35 +551,35 @@ { "data": { "text/plain": [ - "{'a': True,\n", - " 'b': True,\n", - " 'c': True,\n", - " 'd': True,\n", - " 'e': True,\n", - " 'f': True,\n", - " 'g': True,\n", - " 'h': True,\n", - " 'i': True,\n", - " 'j': True,\n", - " 'k': True,\n", - " 'l': True,\n", - " 'm': True,\n", - " 'n': True,\n", - " 'o': True,\n", - " 'p': True,\n", - " 'q': True,\n", - " 'r': True,\n", - " 's': True,\n", + "{'a': False,\n", + " 'b': False,\n", + " 'c': False,\n", + " 'd': False,\n", + " 'e': False,\n", + " 'f': False,\n", + " 'g': False,\n", + " 'h': False,\n", + " 'i': False,\n", + " 'j': False,\n", + " 'k': False,\n", + " 'l': False,\n", + " 'm': False,\n", + " 'n': False,\n", + " 'o': False,\n", + " 'p': False,\n", + " 'q': False,\n", + " 'r': False,\n", + " 's': False,\n", " 't': True,\n", - " 'u': True,\n", - " 'v': True,\n", - " 'w': True,\n", - " 'x': True,\n", - " 'y': True,\n", - " 'z': True}" + " 'u': False,\n", + " 'v': False,\n", + " 'w': False,\n", + " 'x': False,\n", + " 'y': False,\n", + " 'z': False}" ] }, - "execution_count": 17, + "execution_count": 57, "metadata": {}, "output_type": "execute_result" } @@ -527,7 +590,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 48, "metadata": { "collapsed": false }, @@ -578,7 +641,58 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 49, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a : abcdefghijklmnopqrstuvwxyz\n", + "b : a.cde.ghij.lmnop.rst..wx.z\n", + "c : abcdefghijklmnopqrstuvwxyz\n", + "d : abcdefghijklmnopqrstuvwx.z\n", + "e : abcdefghijklmnopqrstuvwxyz\n", + "f : a.cde.ghij.lmnop.rst..wx.z\n", + "g : abcdefghijklmnopqrst.vwxyz\n", + "h : abcdefghijklmnopqrstuvwxyz\n", + "i : abcdefghijklmnopqrstu.wxyz\n", + "j : abcdefghi.klmnopqrstuvwxyz\n", + "k : a.cde.ghij.lmnop.rst..wx.z\n", + "l : abcdefghijklmnopqrstuvwxyz\n", + "m : abcdefghijklmnopqrstuvwxyz\n", + "n : abcdefghijklmnopqrstuvwxyz\n", + "o : abcdefghijklmnopqrstuvwxyz\n", + "p : abcdefghijklmnopqrstuvwxyz\n", + "q : a.cde.ghij.lmnop.rst..wx.z\n", + "r : abcdefghijklmnopqrstuvwxyz\n", + "s : abcdefghijklmnopqrstuvwxyz\n", + "t : abcdefghijklmnopqrstuvwxyz\n", + "u : a.cde..hij.lmnop.rst..wx.z\n", + "v : a.cde.gh.j.lmnop.rst..wx.z\n", + "w : abcdefghijklmnopqrstuvwxyz\n", + "x : abcdefghijklmnopqrstuvwxyz\n", + "y : a.c.e.ghij.lmnop.rst..wx.z\n", + "z : abcdefghijklmnopqrstuvwxyz\n" + ] + } + ], + "source": [ + "for b in sorted(bombe.banks):\n", + " print(b, ': ', end='')\n", + " for w in sorted(bombe.banks[b]):\n", + " if bombe.banks[b][w]:\n", + " print(w, end='')\n", + " else:\n", + " print('.', end='')\n", + " print('')" + ] + }, + { + "cell_type": "code", + "execution_count": 50, "metadata": { "collapsed": false }, @@ -589,7 +703,7 @@ "('a', 'a', 'a')" ] }, - "execution_count": 19, + "execution_count": 50, "metadata": {}, "output_type": "execute_result" } @@ -600,7 +714,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 51, "metadata": { "collapsed": false }, @@ -638,7 +752,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 52, "metadata": { "collapsed": false }, @@ -650,7 +764,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 53, "metadata": { "collapsed": false }, @@ -704,7 +818,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 54, "metadata": { "collapsed": false }, @@ -758,7 +872,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 55, "metadata": { "collapsed": false }, @@ -769,7 +883,7 @@ "1" ] }, - "execution_count": 24, + "execution_count": 55, "metadata": {}, "output_type": "execute_result" } @@ -1051,7 +1165,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 58, "metadata": { "collapsed": false }, @@ -1070,7 +1184,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 59, "metadata": { "collapsed": false }, @@ -1081,7 +1195,7 @@ "('e', 'l', 'e')" ] }, - "execution_count": 38, + "execution_count": 59, "metadata": {}, "output_type": "execute_result" } @@ -1738,7 +1852,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.4.3+" + "version": "3.5.1+" } }, "nbformat": 4, diff --git a/bombe.py b/bombe.py index acaad0e..b8971a7 100644 --- a/bombe.py +++ b/bombe.py @@ -9,6 +9,10 @@ Signal = collections.namedtuple('Signal', ['bank', 'wire']) Connection = collections.namedtuple('Connection', ['banks', 'scrambler']) MenuItem = collections.namedtuple('MenuIem', ['before', 'after', 'number']) +def make_menu(plaintext, ciphertext): + return [MenuItem(p, c, i+1) + for i, (p, c) in enumerate(zip(plaintext, ciphertext))] + class Scrambler(object): def __init__(self, wheel1_spec, wheel2_spec, wheel3_spec, reflector_spec, @@ -82,6 +86,7 @@ class Bombe(object): self.connections += [Connection([bank_before, bank_after], scrambler)] def read_menu(self, menu): + self.connections = [] for item in menu: scrambler = Scrambler(self.wheel1_spec, self.wheel2_spec, self.wheel3_spec, self.reflector_spec, @@ -161,3 +166,16 @@ class Bombe(object): possibles = possibles.union({frozenset((b, inactive[0]))}) return possibles + +def run_multi_bombe(wheel1_spec, wheel2_spec, wheel3_spec, reflector_spec, menu, + start_signal=None, use_diagonal_board=True, + verify_plugboard=True): + allwheels = itertools.product(string.ascii_lowercase, repeat=3) + + with multiprocessing.Pool() as pool: + res = pool.map(Bombe(wheel1_spec, wheel2_spec, wheel3_spec, + reflector_spec, menu=menu, start_signal=start_signal, + use_diagonal_board=use_diagonal_board, + verify_plugboard=verify_plugboard), + allwheels) + return [r[0] for r in res if r[1]] \ No newline at end of file diff --git a/test_bombe.py b/test_bombe.py index 830bb2b..bac7360 100644 --- a/test_bombe.py +++ b/test_bombe.py @@ -2,685 +2,133 @@ import unittest import collections from enigma import * +from bombe import * -class LetterTransformerTest(unittest.TestCase): - - def test_maps1(self): - lt = LetterTransformer([('z', 'a')] + \ - list(zip(string.ascii_lowercase, string.ascii_lowercase[1:])), - raw_transform = True) - self.assertEqual(lt.forward_map, - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0]) - self.assertEqual(lt.backward_map, - [25, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, - 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]) - - - def test_maps2(self): - lt = LetterTransformer(cat(collections.OrderedDict.fromkeys('zyxwc' + string.ascii_lowercase))) - self.assertEqual(lt.forward_map, - [25, 24, 23, 22, 2, 0, 1, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]) - self.assertEqual(lt.backward_map, - [5, 6, 4, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 3, 2, 1, 0]) - - def test_transform(self): - lt = LetterTransformer(cat(collections.OrderedDict.fromkeys('zyxwc' + string.ascii_lowercase))) - self.assertEqual(cat(lt.forward(l) for l in string.ascii_lowercase), - 'zyxwcabdefghijklmnopqrstuv') - self.assertEqual(cat(lt.backward(l) for l in string.ascii_lowercase), - 'fgehijklmnopqrstuvwxyzdcba') - - -class PlugboardTest(unittest.TestCase): - def setUp(self): - self.pb = Plugboard('ua pf rq so ni ey bg hl tx zj'.upper()) - - def test_maps(self): - self.assertEqual(self.pb.forward_map, - [20, 6, 2, 3, 24, 15, 1, 11, 13, 25, 10, 7, 12, - 8, 18, 5, 17, 16, 14, 23, 0, 21, 22, 19, 4, 9]) - self.assertEqual(self.pb.forward_map, self.pb.backward_map) - - def test_transform(self): - self.assertEqual(cat(self.pb.forward(l) - for l in string.ascii_lowercase), - 'ugcdypblnzkhmisfrqoxavwtej') - self.assertEqual(cat(self.pb.backward(l) - for l in string.ascii_lowercase), - 'ugcdypblnzkhmisfrqoxavwtej') - - -class ReflectorTest(unittest.TestCase): +class ScramblerTest(unittest.TestCase): def setUp(self): - self.ref = Reflector(reflector_b_spec) + self.scrambler = Scrambler(wheel_i_spec, wheel_ii_spec, + wheel_iii_spec, reflector_b_spec) - def test_maps(self): - self.assertEqual(self.ref.forward_map, - [24, 17, 20, 7, 16, 18, 11, 3, 15, 23, 13, 6, 14, - 10, 12, 8, 4, 1, 5, 25, 2, 22, 21, 9, 0, 19]) - self.assertEqual(self.ref.forward_map, self.ref.backward_map) - - def test_transform(self): - self.assertEqual(cat(self.ref.forward(l) - for l in string.ascii_lowercase), - 'yruhqsldpxngokmiebfzcwvjat') - self.assertEqual(cat(self.ref.backward(l) - for l in string.ascii_lowercase), - 'yruhqsldpxngokmiebfzcwvjat') + def test_attributes(self): + self.assertEqual(self.scrambler.wheel_positions, (0, 0, 0)) + self.assertEqual(self.scrambler.wheel_positions_l, ('a', 'a', 'a')) - -class SimpleWheelTest(unittest.TestCase): - def test_init1(self): - rotor_1_transform = list(zip(string.ascii_lowercase, - 'EKMFLGDQVZNTOWYHXUSPAIBRCJ'.lower())) - wheel_1 = SimpleWheel(rotor_1_transform, raw_transform=True) - self.assertEqual(cat(wheel_1.forward(l) - for l in string.ascii_lowercase), - 'ekmflgdqvzntowyhxuspaibrcj') - self.assertEqual(cat(wheel_1.backward(l) - for l in string.ascii_lowercase), - 'uwygadfpvzbeckmthxslrinqoj') - - def test_init2(self): - wheel_2 = SimpleWheel(wheel_ii_spec) - self.assertEqual(cat(wheel_2.forward(l) - for l in string.ascii_lowercase), - 'ajdksiruxblhwtmcqgznpyfvoe') - self.assertEqual(cat(wheel_2.backward(l) - for l in string.ascii_lowercase), - 'ajpczwrlfbdkotyuqgenhxmivs') + def test_set_positions(self): + self.scrambler.set_positions(1, 2, 3) + self.assertEqual(self.scrambler.wheel_positions, (1, 2, 3)) + self.assertEqual(self.scrambler.wheel_positions_l, ('b', 'c', 'd')) + self.scrambler.set_positions('p', 'q', 'r') + self.assertEqual(self.scrambler.wheel_positions, (15, 16, 17)) + self.assertEqual(self.scrambler.wheel_positions_l, ('p', 'q', 'r')) def test_advance(self): - wheel_3 = SimpleWheel(wheel_iii_spec) - wheel_3.set_position('a') - wheel_3.advance() - self.assertEqual(cat(wheel_3.forward(l) - for l in string.ascii_lowercase), - 'cegikboqswuymxdhvfzjltrpna') - self.assertEqual(cat(wheel_3.backward(l) - for l in string.ascii_lowercase), - 'zfaobrcpdteumygxhwivkqjnls') - self.assertEqual(wheel_3.position, 1) - self.assertEqual(wheel_3.position_l, 'b') - - for _ in range(24): wheel_3.advance() - - self.assertEqual(wheel_3.position, 25) - self.assertEqual(wheel_3.position_l, 'z') - - self.assertEqual(cat(wheel_3.forward(l) - for l in string.ascii_lowercase), - 'pcegikmdqsuywaozfjxhblnvtr') - self.assertEqual(cat(wheel_3.backward(l) - for l in string.ascii_lowercase), - 'nubhcqdterfvgwoaizjykxmslp') - - wheel_3.advance() - self.assertEqual(wheel_3.position, 0) - self.assertEqual(wheel_3.position_l, 'a') - + self.assertEqual(self.scrambler.wheel_positions, (0, 0, 0)) + self.scrambler.advance() + self.assertEqual(self.scrambler.wheel_positions, (0, 0, 1)) + self.scrambler.advance() + self.assertEqual(self.scrambler.wheel_positions, (0, 0, 2)) + self.scrambler.set_positions(0, 0, 25) + self.assertEqual(self.scrambler.wheel_positions, (0, 0, 25)) + self.scrambler.advance() + self.assertEqual(self.scrambler.wheel_positions, (0, 0, 0)) + self.scrambler.set_positions(0, 0, 25) + self.scrambler.advance(wheel3=False) + self.assertEqual(self.scrambler.wheel_positions, (0, 0, 25)) + self.scrambler.set_positions(0, 0, 25) + self.scrambler.advance(wheel2=True) + self.assertEqual(self.scrambler.wheel_positions, (0, 1, 0)) + self.scrambler.set_positions(0, 0, 25) + self.scrambler.advance(wheel1=True, wheel2=True) + self.assertEqual(self.scrambler.wheel_positions, (1, 1, 0)) + + def test_lookups(self): + self.scrambler.set_positions(0, 0, 0) + self.assertEqual(cat(self.scrambler.lookup(l) + for l in string.ascii_lowercase), + 'uejobtpzwcnsrkdgvmlfaqiyxh') + self.assertEqual(cat(self.scrambler.lookup(l) + for l in 'uejobtpzwcnsrkdgvmlfaqiyxh'), + 'abcdefghijklmnopqrstuvwxyz') + self.scrambler.set_positions('p', 'q', 'r') + self.assertEqual(cat(self.scrambler.lookup(l) + for l in string.ascii_lowercase), + 'jgqmnwbtvaurdezxclyhkifpso') + self.assertEqual(cat(self.scrambler.lookup(l) + for l in 'jgqmnwbtvaurdezxclyhkifpso'), + 'abcdefghijklmnopqrstuvwxyz') - self.assertEqual(cat(wheel_3.forward(l) - for l in string.ascii_lowercase), - 'bdfhjlcprtxvznyeiwgakmusqo') - self.assertEqual(cat(wheel_3.backward(l) - for l in string.ascii_lowercase), - 'tagbpcsdqeufvnzhyixjwlrkom') - - -class SimpleWheelTest(unittest.TestCase): - def test_init1(self): - wheel = Wheel(wheel_iii_spec, wheel_iii_pegs, position='b', - ring_setting=1) - self.assertEqual(wheel.position, 1) - self.assertEqual(wheel.peg_positions, [20]) - self.assertEqual(wheel.position_l, 'b') - - wheel.advance() - self.assertEqual(wheel.position, 2) - self.assertEqual(wheel.peg_positions, [19]) - self.assertEqual(wheel.position_l, 'c') - - def test_init2(self): - wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b', - ring_setting=3) - self.assertEqual(wheel.position, 25) - self.assertIn(11, wheel.peg_positions) - self.assertIn(24, wheel.peg_positions) - self.assertEqual(wheel.position_l, 'b') - self.assertEqual(cat(wheel.forward(l) - for l in string.ascii_lowercase), - 'xkqhwpvngzrcfoiaselbtymjdu') - self.assertEqual(cat(wheel.backward(l) - for l in string.ascii_lowercase), - 'ptlyrmidoxbswhnfckquzgeavj') - - - def test_advance(self): - wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b', - ring_setting=3) - wheel.advance() - - self.assertEqual(wheel.position, 0) - self.assertIn(10, wheel.peg_positions) - self.assertIn(23, wheel.peg_positions) - self.assertEqual(wheel.position_l, 'c') - self.assertEqual(cat(wheel.forward(l) - for l in string.ascii_lowercase), - 'jpgvoumfyqbenhzrdkasxlictw') - self.assertEqual(cat(wheel.backward(l) - for l in string.ascii_lowercase), - 'skxqlhcnwarvgmebjptyfdzuio') - - def test_advance_23(self): - wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b', - ring_setting=3) - for _ in range(23): - wheel.advance() - - self.assertEqual(wheel.position, 22) - self.assertIn(1, wheel.peg_positions) - self.assertIn(14, wheel.peg_positions) - self.assertEqual(wheel.position_l, 'y') - self.assertEqual(cat(wheel.forward(l) - for l in string.ascii_lowercase), - 'mgxantkzsyqjcufirldvhoewbp') - self.assertEqual(cat(wheel.backward(l) - for l in string.ascii_lowercase), - 'dymswobuplgraevzkqifntxcjh') - - def test_advance_24(self): - wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b', - ring_setting=3) - for _ in range(24): - wheel.advance() - - self.assertEqual(wheel.position, 23) - self.assertIn(0, wheel.peg_positions) - self.assertIn(13, wheel.peg_positions) - self.assertEqual(wheel.position_l, 'z') - self.assertEqual(cat(wheel.forward(l) - for l in string.ascii_lowercase), - 'fwzmsjyrxpibtehqkcugndvaol') - self.assertEqual(cat(wheel.backward(l) - for l in string.ascii_lowercase), - 'xlrvnatokfqzduyjphemswbigc') - - def test_advance_25(self): - wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b', - ring_setting=3) - for _ in range(25): - wheel.advance() - - self.assertEqual(wheel.position, 24) - self.assertIn(25, wheel.peg_positions) - self.assertIn(12, wheel.peg_positions) - self.assertEqual(wheel.position_l, 'a') - self.assertEqual(cat(wheel.forward(l) - for l in string.ascii_lowercase), - 'vylrixqwohasdgpjbtfmcuznke') - self.assertEqual(cat(wheel.backward(l) - for l in string.ascii_lowercase), - 'kqumzsnjepyctxiogdlrvahfbw') - - def test_advance_26(self): - wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b', - ring_setting=3) - for _ in range(26): - wheel.advance() - - self.assertEqual(wheel.position, 25) - self.assertIn(24, wheel.peg_positions) - self.assertIn(11, wheel.peg_positions) - self.assertEqual(wheel.position_l, 'b') - self.assertEqual(cat(wheel.forward(l) - for l in string.ascii_lowercase), - 'xkqhwpvngzrcfoiaselbtymjdu') - self.assertEqual(cat(wheel.backward(l) - for l in string.ascii_lowercase), - 'ptlyrmidoxbswhnfckquzgeavj') - - - def test_advance_27(self): - wheel = Wheel(wheel_vi_spec, wheel_vi_pegs, position='b', - ring_setting=3) - for _ in range(27): - wheel.advance() - - self.assertEqual(wheel.position, 0) - self.assertIn(23, wheel.peg_positions) - self.assertIn(10, wheel.peg_positions) - self.assertEqual(wheel.position_l, 'c') - self.assertEqual(cat(wheel.forward(l) - for l in string.ascii_lowercase), - 'jpgvoumfyqbenhzrdkasxlictw') - self.assertEqual(cat(wheel.backward(l) - for l in string.ascii_lowercase), - 'skxqlhcnwarvgmebjptyfdzuio') - -class EnigmaTest(unittest.TestCase): - +class BombeTest(unittest.TestCase): def setUp(self): - self.enigma = Enigma(reflector_b_spec, - wheel_i_spec, wheel_i_pegs, - wheel_ii_spec, wheel_ii_pegs, - wheel_iii_spec, wheel_iii_pegs, - 1, 1, 1, - '') - - # Setting sheet line 31 from http://www.codesandciphers.org.uk/enigma/enigma3.htm - # Enigma simulation settings are - # http://enigma.louisedade.co.uk/enigma.html?m3;b;b153;AFTX;AJEU;AU-BG-EY-FP-HL-IN-JZ-OS-QR-TX - self.enigma31 = Enigma(reflector_b_spec, - wheel_i_spec, wheel_i_pegs, - wheel_v_spec, wheel_v_pegs, - wheel_iii_spec, wheel_iii_pegs, - 6, 20, 24, - 'ua pf rq so ni ey bg hl tx zj') - - - def test_middle_advance(self): - self.enigma.set_wheels('a', 'a', 't') - self.assertEqual(self.enigma.wheel_positions, (0, 0, 19)) - self.assertEqual(cat(self.enigma.wheel_positions_l), 'aat') - self.assertEqual(self.enigma.peg_positions, ([16], [4], [2])) - self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase), - 'puvioztjdhxmlyeawsrgbcqknf') - - self.enigma.advance() - self.assertEqual(self.enigma.wheel_positions, (0, 0, 20)) - self.assertEqual(cat(self.enigma.wheel_positions_l), 'aau') - self.assertEqual(self.enigma.peg_positions, ([16], [4], [1])) - self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase), - 'baigpldqcowfyzjehvtsxrkumn') - - self.enigma.advance() - self.assertEqual(self.enigma.wheel_positions, (0, 0, 21)) - self.assertEqual(cat(self.enigma.wheel_positions_l), 'aav') - self.assertEqual(self.enigma.peg_positions, ([16], [4], [0])) - self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase), - 'mnvfydiwgzsoablrxpkutchqej') - - self.enigma.advance() - self.assertEqual(self.enigma.wheel_positions, (0, 1, 22)) - self.assertEqual(cat(self.enigma.wheel_positions_l), 'abw') - self.assertEqual(self.enigma.peg_positions, ([16], [3], [25])) - self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase), - 'ulfopcykswhbzvderqixanjtgm') - - self.enigma.advance() - self.assertEqual(self.enigma.wheel_positions, (0, 1, 23)) - self.assertEqual(cat(self.enigma.wheel_positions_l), 'abx') - self.assertEqual(self.enigma.peg_positions, ([16], [3], [24])) - self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase), - 'qmwftdyovursbzhxaklejicpgn') - - self.enigma.advance() - self.assertEqual(self.enigma.wheel_positions, (0, 1, 24)) - self.assertEqual(cat(self.enigma.wheel_positions_l), 'aby') - self.assertEqual(self.enigma.peg_positions, ([16], [3], [23])) - self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase), - 'oljmzxrvucybdqasngpwihtfke') - - - def test_double_advance(self): - self.enigma.set_wheels('a', 'd', 't') - self.assertEqual(self.enigma.wheel_positions, (0, 3, 19)) - self.assertEqual(cat(self.enigma.wheel_positions_l), 'adt') - self.assertEqual(self.enigma.peg_positions, ([16], [1], [2])) - self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase), - 'zcbpqxwsjiuonmldethrkygfva') - - self.enigma.advance() - self.assertEqual(self.enigma.wheel_positions, (0, 3, 20)) - self.assertEqual(cat(self.enigma.wheel_positions_l), 'adu') - self.assertEqual(self.enigma.peg_positions, ([16], [1], [1])) - self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase), - 'ehprawjbngotxikcsdqlzyfmvu') - - self.enigma.advance() - self.assertEqual(self.enigma.wheel_positions, (0, 3, 21)) - self.assertEqual(cat(self.enigma.wheel_positions_l), 'adv') - self.assertEqual(self.enigma.peg_positions, ([16], [1], [0])) - self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase), - 'eqzxarpihmnvjkwgbfuyslodtc') - - self.enigma.advance() - self.assertEqual(self.enigma.wheel_positions, (0, 4, 22)) - self.assertEqual(cat(self.enigma.wheel_positions_l), 'aew') - self.assertEqual(self.enigma.peg_positions, ([16], [0], [25])) - self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase), - 'qedcbtpluzmhkongavwfirsyxj') - - self.enigma.advance() - self.assertEqual(self.enigma.wheel_positions, (1, 5, 23)) - self.assertEqual(cat(self.enigma.wheel_positions_l), 'bfx') - self.assertEqual(self.enigma.peg_positions, ([15], [25], [24])) - self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase), - 'iwuedhsfazqxytvrkpgncoblmj') - - self.enigma.advance() - self.assertEqual(self.enigma.wheel_positions, (1, 5, 24)) - self.assertEqual(cat(self.enigma.wheel_positions_l), 'bfy') - self.assertEqual(self.enigma.peg_positions, ([15], [25], [23])) - self.assertEqual(cat(self.enigma.lookup(l) for l in string.ascii_lowercase), - 'baknstqzrmcxjdvygiefwoulph') - - - def test_simple_encipher(self): - self.enigma.set_wheels('a', 'a', 'a') - ct = self.enigma.encipher('testmessage') - self.assertEqual(ct, 'olpfhnvflyn') - - self.enigma.set_wheels('a', 'd', 't') - ct = self.enigma.encipher('testmessage') - self.assertEqual(ct, 'lawnjgpwjik') - - self.enigma.set_wheels('b', 'd', 'q') - ct = self.enigma.encipher('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') - self.assertEqual(ct, - 'kvmmwrlqlqsqpeugjrcxzwpfyiyybwloewrouvkpoztceuwtfjzqwpbqldttsr') - self.assertEqual(cat(self.enigma.wheel_positions_l), 'cha') - - - def test_advance_with_ring_settings(self): - self.enigma31.set_wheels('j', 'e', 'u') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (4, 11, 24)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jev') - self.assertEqual(self.enigma31.peg_positions, ([7], [21], [0])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'mvqjlyowkdieasgzcunxrbhtfp') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (4, 12, 25)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jfw') - self.assertEqual(self.enigma31.peg_positions, ([7], [20], [25])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'sjolzuyvrbwdpxcmtiaqfhknge') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (4, 12, 0)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jfx') - self.assertEqual(self.enigma31.peg_positions, ([7], [20], [24])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'qrxedkoywufmlvgsabpzjnicht') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (4, 12, 1)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jfy') - self.assertEqual(self.enigma31.peg_positions, ([7], [20], [23])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'hpsukliagqefwvtbjxcodnmrzy') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (4, 12, 2)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jfz') - self.assertEqual(self.enigma31.peg_positions, ([7], [20], [22])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'zevnbpyqowrtxdifhkulscjmga') - - - def test_advance_with_ring_settings_2(self): - self.enigma31.set_wheels('i', 'd', 'z') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 3)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ida') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [21])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'ikhpqrvcambzjondefwyxgsutl') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 4)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idb') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [20])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'cdabskhgzwfmlqvunyexpojtri') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 5)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idc') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [19])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'pcbwiqhgemyvjsuaftnroldzkx') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 6)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idd') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [18])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'xcbfvdnouptmlghjzwykierasq') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 7)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ide') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [17])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'xfvglbdynuseriwqpmkzjcoaht') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 8)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idf') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [16])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'tfpqlbouynsewjgcdxkahzmriv') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 9)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idg') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [15])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'cjaunvlwtbygzexrspqidfhokm') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 10)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idh') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [14])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'yltxkrqvowebzpingfucshjdam') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 11)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idi') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [13])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'myktluzrnxceaiqsohpdfwvjbg') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 12)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idj') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [12])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'pynjrmiugdqxfcvakewzhoslbt') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 13)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idk') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [11])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'mwvedyplnoxhaijgrqtszcbkfu') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 14)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idl') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [10])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'qcbrfeutvoxpnmjladzhgiykws') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 15)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idm') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [9])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'dnoahryetsmukbcvwfjilpqzgx') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 16)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idn') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [8])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'nidcfehgbqsovalyjzkxwmutpr') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 17)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ido') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [7])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'joifxdulcarhzpbntkwqgysevm') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 18)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idp') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [6])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'ptnlsxvozmwdjchayuebrgkfqi') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 19)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idq') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [5])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'slwopzqnmxybihdeguavrtcjkf') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 20)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idr') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [4])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'hcbedwlamzogixkytsrqvufnpj') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 21)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ids') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [3])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'odxbjwzrmelkisavuhnyqpfctg') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 22)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idt') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [2])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'udgbfeclrwnhxksvtioqapjmzy') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 23)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idu') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [1])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'nrdczqxmowvshaiufblypkjgte') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 10, 24)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'idv') - self.assertEqual(self.enigma31.peg_positions, ([8], [22], [0])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'hkifjdoacebqtzgulyvmpsxwrn') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 11, 25)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'iew') - self.assertEqual(self.enigma31.peg_positions, ([8], [21], [25])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'yptzuhofqvnmlkgbixwcejsrad') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 11, 0)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'iex') - self.assertEqual(self.enigma31.peg_positions, ([8], [21], [24])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'vkdcwhqfjibzsptngumoraeyxl') - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (3, 11, 1)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'iey') - self.assertEqual(self.enigma31.peg_positions, ([8], [21], [23])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'wenpbqrouxlkychdfgzvitajms') - - def test_double_advance_with_ring_settings_2(self): - self.enigma31.set_wheels('a', 'y', 't') - self.assertEqual(self.enigma31.wheel_positions, (21, 5, 22)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ayt') - self.assertEqual(self.enigma31.peg_positions, ([16], [1], [2])) - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (21, 5, 23)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ayu') - self.assertEqual(self.enigma31.peg_positions, ([16], [1], [1])) - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (21, 5, 24)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'ayv') - self.assertEqual(self.enigma31.peg_positions, ([16], [1], [0])) - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (21, 6, 25)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'azw') - self.assertEqual(self.enigma31.peg_positions, ([16], [0], [25])) - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (22, 7, 0)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bax') - self.assertEqual(self.enigma31.peg_positions, ([15], [25], [24])) - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (22, 7, 1)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bay') - self.assertEqual(self.enigma31.peg_positions, ([15], [25], [23])) - - self.enigma31.set_wheels('a', 'z', 't') - self.assertEqual(self.enigma31.wheel_positions, (21, 6, 22)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'azt') - self.assertEqual(self.enigma31.peg_positions, ([16], [0], [2])) - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (22, 7, 23)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bau') - self.assertEqual(self.enigma31.peg_positions, ([15], [25], [1])) - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (22, 7, 24)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bav') - self.assertEqual(self.enigma31.peg_positions, ([15], [25], [0])) - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (22, 8, 25)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bbw') - self.assertEqual(self.enigma31.peg_positions, ([15], [24], [25])) - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (22, 8, 0)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bbx') - self.assertEqual(self.enigma31.peg_positions, ([15], [24], [24])) - - self.enigma31.advance() - self.assertEqual(self.enigma31.wheel_positions, (22, 8, 1)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'bby') - self.assertEqual(self.enigma31.peg_positions, ([15], [24], [23])) - - - def test_encipher_with_ring(self): - - self.enigma31.set_wheels('i', 'z', 'd') - ct = self.enigma31.encipher('verylongtestmessagewithanextrabitofmessageforgoodmeasure') - self.assertEqual(ct, - 'apocwtjuikurcfivlozvhffkoacxufcekthcvodfqpxdjqyckdozlqki') - self.assertEqual(self.enigma31.wheel_positions, (4, 9, 10)) - self.assertEqual(cat(self.enigma31.wheel_positions_l), 'jch') - self.assertEqual(self.enigma31.peg_positions, ([7], [23], [14])) - self.assertEqual(cat(self.enigma31.lookup(l) for l in string.ascii_lowercase), - 'mopnigfuesqwadbcktjrhylzvx') - - self.enigma31.set_wheels('i', 'z', 'd') - pt = self.enigma31.decipher('apocwtjuikurcfivlozvhffkoacxufcekthcvodfqpxdjqyckdozlqki') - self.assertEqual(pt, - 'verylongtestmessagewithanextrabitofmessageforgoodmeasure') + self.bombe = Bombe(wheel_i_spec, wheel_ii_spec, + wheel_iii_spec, reflector_b_spec) + self.plaintext = 'thisisatestmessage' + self.ciphertext = 'opgndxcrwomnlnecjz' + self.menu = make_menu(self.plaintext, self.ciphertext) + self.bombe.read_menu(self.menu) + + def test_menu(self): + self.assertEqual(len(self.bombe.connections), 18) + self.assertEqual(':'.join(sorted(cat(sorted(c.banks)) + for c in self.bombe.connections)), + 'ac:ac:di:el:es:ew:ez:gi:gj:hp:mn:mt:ns:ns:os:ot:rt:sx') + self.assertEqual(':'.join(sorted(cat(c.scrambler.wheel_positions_l) + for c in self.bombe.connections)), + 'aaa:aab:aac:aad:aae:aaf:aag:aah:aai:aaj:aak:aal:aam:aan:aao:aap:aaq:aar') + + self.bombe.read_menu(self.menu) + self.assertEqual(len(self.bombe.connections), 18) + + def test_signal(self): + self.bombe.test(Signal('t', 't')) + self.assertEqual(len(self.bombe.banks['t']), 26) + self.assertTrue(all(self.bombe.banks['t'].values())) + self.assertEqual(sum(1 for s in self.bombe.banks['u'].values() if s), 18) + + self.bombe.set_positions('a', 'a', 'b') + self.bombe.test() + self.assertEqual(sum(1 for b in self.bombe.banks + for s in self.bombe.banks[b].values() if s), + 11) + + def test_valid_with_rings(self): + pt31 = 'someplaintext' + ct31 = 'dhnpforeeimgg' + menu31 = make_menu(pt31, ct31) + b31 = Bombe(wheel_i_spec, wheel_v_spec, wheel_iii_spec, reflector_b_spec) + b31.read_menu(menu31) + b31.set_positions('e', 'l', 'f') + + b31.test(Signal('s', 'o')) + self.assertEqual(sum(1 for b in b31.banks + for s in b31.banks[b].values() if s), + 5) + self.assertEqual(':'.join(sorted(cat(sorted(p)) + for p in b31.possible_plugboards())), + 'd:hl:os') + + b31.test(Signal('o', 'o')) + self.assertEqual(sum(1 for b in b31.banks + for s in b31.banks[b].values() if s), + 507) + self.assertEqual(':'.join(sorted(cat(sorted(p)) + for p in b31.possible_plugboards())), + 'bg:ey:fp:in:m:tx') + + def test_invalid_with_rings(self): + pt31 = 'someplaintext' + ct31 = 'dhnpforeeimgg' + menu31 = make_menu(pt31, ct31) + b31 = Bombe(wheel_i_spec, wheel_v_spec, wheel_iii_spec, reflector_b_spec) + b31.read_menu(menu31) + b31.set_positions('a', 'a', 'a') + + b31.test(Signal('a', 'o')) + self.assertEqual(sum(1 for b in b31.banks + for s in b31.banks[b].values() if s), + 514) + self.assertEqual(':'.join(sorted(cat(sorted(p)) + for p in b31.possible_plugboards())), + '') if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() -- 2.34.1