changeset 1:9a403915a740

Added some Rotor tests.
author Brian Neal <bgneal@gmail.com>
date Fri, 25 May 2012 23:42:45 -0500
parents 2426d1d52025
children 81665fcaa36d
files enigma/rotors/rotor.py enigma/tests/__init__.py enigma/tests/test_rotor.py
diffstat 2 files changed, 99 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- 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.
--- /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)