From 998bb596ef49cad87a6fe9153956bf99df54a9bf Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Wed, 25 Nov 2009 23:12:55 -0500 Subject: [PATCH] starting to implement a pad filler + tests --- onetimepad.py | 31 +++++++++++++++++++++++++++++-- test_onetimepad.py | 38 ++++++++++++++++++++++++++++++++------ 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/onetimepad.py b/onetimepad.py index ca626b9..a535d41 100644 --- a/onetimepad.py +++ b/onetimepad.py @@ -12,7 +12,7 @@ def decode(msg, pad): def create_pad(length, width=72): chars = _create_chars_for_pad(length) lines = _chunk_chars_into_lines(chars, width=width) - return lines + return '\n\n\n'.join(lines) def _create_chars_for_pad(length): @@ -26,7 +26,7 @@ def _chunk_chars_into_lines(chars, width=72): lines = [] for chunk in _as_line_chunks(chars, width=width): lines.append(chunk) - return '\n\n\n'.join(lines) + return lines def _as_line_chunks(chars, width=72): @@ -41,6 +41,33 @@ def _as_line_chunks(chars, width=72): yield ''.join(chunk) +def _padfill(text, pad): + padlines = pad.splitlines() + textlines = _chunk_chars_into_lines(text, _get_textwidth(pad)) + for lineno, padline in enumerate(padlines[:]): + if _is_padline(lineno) or _is_cypherline(lineno): + continue + else: + padlines[lineno] = textlines.pop(0) if textlines[1:] else '' + return '\n'.join(padlines) + + +def _get_textwidth(text): + return max([len(line) for line in text.splitlines()]) + + +def _is_padline(lineno): + return not lineno % 3 + + +def _is_txtline(lineno): + return (lineno % 2 and not lineno % 3) + + +def _is_cypherline(lineno): + return lineno % 3 + + def _mk_as_alpha(): as_alpha = dict() a_chr = ord('A') diff --git a/test_onetimepad.py b/test_onetimepad.py index fd27e97..680b83a 100644 --- a/test_onetimepad.py +++ b/test_onetimepad.py @@ -1,10 +1,10 @@ -import random - import unittest import onetimepad as OT class TestOneTimePad(unittest.TestCase): + msg = ('HOWMUCHCHUCKCOULDAWOODCHUCKCHUCKIFA' + 'WOODCHUCKCOULDCHUCKWOOD' * 50) def test_mk_as_alpha_excludes_j(self): self.assertTrue('J' not in OT._AS_ALPHA.values()) @@ -20,14 +20,40 @@ class TestOneTimePad(unittest.TestCase): def test_two_out_of_every_three_lines_are_empty_on_new_pad(self): pad = OT.create_pad(2000) - for i, line in enumerate(pad.splitlines()): - lineno = i + 3 - if not lineno % 3: + for lineno, line in enumerate(pad.splitlines()): + line = line.strip() + if OT._is_padline(lineno): self.assertTrue(bool(len(line)), - 'line {0} is non-empty'.format(lineno)) + 'pad line {0} is non-empty'.format(lineno)) + elif OT._is_txtline(lineno): + self.assertFalse(bool(len(line)), + 'text line {0} is empty'.format(lineno)) + elif OT._is_cypherline(lineno): + self.assertFalse(bool(len(line)), + 'cypher line {0} is empty'.format(lineno)) else: + raise NotImplementedError(lineno) + + def test_padfill_leaves_every_third_line_empty(self): + msg = self.msg[:] + pad = OT.create_pad(len(msg)) + filled = OT._padfill(msg, pad) + # print filled + # raise Exception + self.assertTrue(bool(filled)) + for lineno, line in enumerate(filled.splitlines()): + line = line.strip() + if OT._is_cypherline(lineno): self.assertFalse(bool(len(line)), 'line {0} is empty'.format(lineno)) + elif OT._is_txtline(lineno): + self.assertTrue(bool(len(line)), + 'text line {0} is non-empty'.format(lineno)) + elif OT._is_padline(lineno): + self.assertTrue(bool(len(line)), + 'pad line {0} is non-empty'.format(lineno)) + else: + raise NotImplementedError(lineno) if __name__ == '__main__':