# HG changeset patch # User Brian Neal # Date 1338007365 18000 # Node ID 9a403915a7405ca37188d930ddda7724190bfc41 # Parent 2426d1d52025eb4caade819b432cba759c142432 Added some Rotor tests. diff -r 2426d1d52025 -r 9a403915a740 enigma/rotors/rotor.py --- a/enigma/rotors/rotor.py Fri May 25 19:38:22 2012 -0500 +++ b/enigma/rotors/rotor.py Fri May 25 23:42:45 2012 -0500 @@ -12,6 +12,8 @@ class RotorError(Exception): pass +ALPHA_LABELS = string.ascii_uppercase +NUMERIC_LABELS = ['{:02d}'.format(n) for n in range(1, 27)] # In specifying a wiring for a rotor, every letter must be included exactly # once. This variable helps us enforce that: @@ -91,7 +93,6 @@ self.name = model_name self.wiring_str = wiring.upper() self.ring_setting = ring_setting - self.stepping_parms = stepping self.alpha_labels = alpha_labels self.pos = None # not installed in an Enigma machine yet @@ -123,14 +124,28 @@ self.exit_map[v] = i # configure ring labels - if alpha_labels: - self.ring_labels = string.ascii_uppercase - else: - self.ring_labels = ['{:02d}'.format(n) for n in range(1, 27)] + self.ring_labels = ALPHA_LABELS if alpha_labels else NUMERIC_LABELS # for mapping window display values to indices self.display_map = dict(zip(self.ring_labels, range(26))) + # build step list: this is a list of positions where our notches are in + # place to allow the pawls to move + step_list = [] + if isinstance(stepping, str): + step_list = [stepping] + elif isinstance(stepping, tuple) or isinstance(stepping, list): + step_list = stepping + elif stepping is not None: + raise RotorError("stepping") + + self.step_set = set() + for pos in step_list: + if pos in self.display_map: + self.step_set.add(self.display_map[pos]) + else: + raise RotorError("stepping: %s" % pos) + def set_display(self, val): """Spin the rotor such that the string val appears in the operator window. diff -r 2426d1d52025 -r 9a403915a740 enigma/tests/test_rotor.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/enigma/tests/test_rotor.py Fri May 25 23:42:45 2012 -0500 @@ -0,0 +1,79 @@ +"""test_rotor.py - Unit tests for the Rotor class for the Enigma simulation.""" +# Copyright (C) 2012 by Brian Neal. +# This file is part of Py-Enigma, the Enigma Machine simulation. +# Py-Enigma is released under the MIT License (see License.txt). + +import unittest +import string + +from rotors.rotor import Rotor, RotorError, ALPHA_LABELS, NUMERIC_LABELS + + +WIRING = 'EKMFLGDQVZNTOWYHXUSPAIBRCJ' + + +class SimpleRotorTestCase(unittest.TestCase): + """Basic tests to verify Rotor functionality""" + + def test_bad_wiring(self): + + self.assertRaises(RotorError, Rotor, 'I', '') + self.assertRaises(RotorError, Rotor, 'I', 'ABC') + self.assertRaises(RotorError, Rotor, 'I', '123') + + w = string.punctuation[:26] + self.assertRaises(RotorError, Rotor, 'I', w) + + w = 'ABCD' * 7 + self.assertRaises(RotorError, Rotor, 'III', w[:26]) + + def test_bad_ring_setting(self): + + self.assertRaises(RotorError, Rotor, 'I', WIRING, ring_setting=-1) + self.assertRaises(RotorError, Rotor, 'I', WIRING, ring_setting=26) + self.assertRaises(RotorError, Rotor, 'I', WIRING, ring_setting='A') + self.assertRaises(RotorError, Rotor, 'I', WIRING, ring_setting=None) + + def test_bad_stepping(self): + + for alpha in True, False: + self.assertRaises(RotorError, Rotor, 'I', WIRING, + alpha_labels=alpha, stepping="0") + self.assertRaises(RotorError, Rotor, 'I', WIRING, + alpha_labels=alpha, stepping="A0") + self.assertRaises(RotorError, Rotor, 'I', WIRING, + alpha_labels=alpha, stepping=[1]) + self.assertRaises(RotorError, Rotor, 'I', WIRING, + alpha_labels=alpha, stepping=['A', '%', '14']) + self.assertRaises(RotorError, Rotor, 'I', WIRING, + alpha_labels=alpha, stepping=('A', '%', '14')) + + def test_alpha_display(self): + + for r in range(26): + rotor = Rotor('I', WIRING, ring_setting=r, alpha_labels=True) + for s in ALPHA_LABELS: + rotor.set_display(s) + self.assertEqual(s, rotor.get_display()) + + def test_numeric_display(self): + + for r in range(26): + rotor = Rotor('I', WIRING, ring_setting=r, alpha_labels=False) + for s in NUMERIC_LABELS: + rotor.set_display(s) + self.assertEqual(s, rotor.get_display()) + + def test_wiring(self): + rotor = Rotor('I', WIRING, ring_setting=0, alpha_labels=True) + rotor.set_display('A') + + for i, s in enumerate(ALPHA_LABELS): + pos = ord(s) - ord('A') + output = rotor.signal_in(pos) + + expected = ord(WIRING[i]) - ord('A') + self.assertEqual(output, expected) + + output = rotor.signal_out(expected) + self.assertEqual(output, i)