# HG changeset patch # User Brian Neal # Date 1371264402 18000 # Node ID 425981f2787602d5e088b4fd35a70e270193bbec # Parent b6b52d63cd504ec9fe8142203d53be58f634e643 More work on generating a key list. Added some tests. TODO: need to account for not all wheels having all the letters. diff -r b6b52d63cd50 -r 425981f27876 m209/keylist/generate.py --- a/m209/keylist/generate.py Fri Jun 14 20:11:41 2013 -0500 +++ b/m209/keylist/generate.py Fri Jun 14 21:46:42 2013 -0500 @@ -95,10 +95,27 @@ if not (0.4 <= ratio <= 0.6): return False - # Check for more than 6 consecutive effective pins - # TODO + # Check for more than 6 consecutive effective pins on a wheel + # TODO: not all letters are on every wheel - # Check for more than 6 consecutive ineffective pins - # TODO + for pins in pin_list: + run = 0 + for i in range(len(pins) - 1): + if ord(pins[i]) + 1 == ord(pins[i + 1]): + run = 2 if run == 0 else run + 1 + else: + run = 0 + if run >= 7: + return False + + # Check for more than 6 consecutive ineffective pins on a wheel + # TODO: not all letters are on every wheel + + for pins in pin_list: + x = 'A' + for y in pins: + if ord(y) - ord(x) >= 8: + return False + x = y return True diff -r b6b52d63cd50 -r 425981f27876 m209/keylist/tests/test_generate.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m209/keylist/tests/test_generate.py Fri Jun 14 21:46:42 2013 -0500 @@ -0,0 +1,103 @@ +# Copyright (C) 2013 by Brian Neal. +# This file is part of m209, the M-209 simulation. +# m209 is released under the MIT License (see LICENSE.txt). + +"""Tests for the key list generator functions.""" + +import collections +import random +import unittest + +from ..generate import generate_key_list, pin_list_check +from m209.converter import M209 +from m209.data import KEY_WHEEL_DATA + + +def make_pin_list(eff_cnt): + """Generates a pin list with an effect pin count given by eff_cnt.""" + cards = [1] * eff_cnt + cards.extend([0] * (131 - len(cards))) + random.shuffle(cards) + deck = collections.deque(cards) + pin_list = [] + for letters, _ in KEY_WHEEL_DATA: + pins = [c for c in letters if deck.pop()] + pin_list.append(''.join(pins)) + + return pin_list + + +class GenerateTestCase(unittest.TestCase): + + def setUp(self): + + self.valid_pin_list = [ + 'FGIKOPRSUVWYZ', + 'DFGKLMOTUY', + 'ADEFGIORTUVX', + 'ACFGHILMRSU', + 'BCDEFJKLPS', + 'EFGHIJLMNP' + ] + + def test_generate_key_list(self): + + key_list = generate_key_list('BN') + self.assertEqual(key_list.indicator, 'BN') + self.assertTrue(isinstance(key_list.pin_list, list)) + self.assertEqual(len(key_list.pin_list), 6) + + for i, pins in enumerate(key_list.pin_list): + self.assertTrue(all(c in KEY_WHEEL_DATA[i][0] for c in pins)) + + # TODO: add some lug asserts + + m_209 = M209(lugs=key_list.lugs, pin_list=key_list.pin_list) + m_209.set_key_wheels('AAAAAA') + s = m_209.encrypt('A' * 26) + self.assertEqual(s, key_list.letter_check) + + def test_pin_list_check(self): + + # Effective pin ratio too high (100%) + all_pins = [t[0] for t in KEY_WHEEL_DATA] + self.assertEqual(False, pin_list_check(all_pins)) + + # Effective pin ratio too low (0%) + no_pins = ['' for i in range(6)] + self.assertEqual(False, pin_list_check(no_pins)) + + # Effective pin ratio too low (< 40%) + self.assertFalse(pin_list_check(make_pin_list(10))) + self.assertFalse(pin_list_check(make_pin_list(20))) + self.assertFalse(pin_list_check(make_pin_list(30))) + self.assertFalse(pin_list_check(make_pin_list(40))) + self.assertFalse(pin_list_check(make_pin_list(50))) + + # Effective pin ratio too high (< 60%) + self.assertFalse(pin_list_check(make_pin_list(79))) + self.assertFalse(pin_list_check(make_pin_list(85))) + self.assertFalse(pin_list_check(make_pin_list(95))) + self.assertFalse(pin_list_check(make_pin_list(100))) + self.assertFalse(pin_list_check(make_pin_list(125))) + + def test_consecutive_effective_pins(self): + + pin_list = self.valid_pin_list + pin_list[0] = 'ABEGHIJKLNOSUZ' + self.assertTrue(pin_list_check(pin_list)) + pin_list[0] = 'ABEGHIJKLM' + self.assertFalse(pin_list_check(pin_list)) + pin_list[0] = 'ABEGHIJKLMN' + self.assertFalse(pin_list_check(pin_list)) + pin_list[0] = 'ABCDEFGHIJ' + self.assertFalse(pin_list_check(pin_list)) + pin_list[0] = 'BDJKLMNOPTW' + self.assertFalse(pin_list_check(pin_list)) + pin_list[0] = 'BEFGHIJKSUX' + self.assertFalse(pin_list_check(pin_list)) + + def test_consecutive_noneffective_pins(self): + pass + +