Browse Source

Merge branch 'feature/tests-framework' into develop

tags/v0.1^2
Ben Kurtovic 12 years ago
parent
commit
b3329c75fd
7 changed files with 244 additions and 4 deletions
  1. +1
    -2
      bot/blowfish.py
  2. +1
    -1
      bot/commands/calc.py
  3. +1
    -1
      bot/commands/help.py
  4. +96
    -0
      tests/support.py
  5. +77
    -0
      tests/test_blowfish.py
  6. +39
    -0
      tests/test_calc.py
  7. +29
    -0
      tests/test_test.py

+ 1
- 2
bot/blowfish.py View File

@@ -514,8 +514,7 @@ def encrypt(key, plaintext):

def decrypt(key, cyphertext):
"""Decrypt the result of encrypt() using the original key, or raise
IncorrectKeyError(). If the cyphertext is malformed, raise
BadCyphertextError()."""
DecryptionError()."""
cypher = Blowfish(key)

try:


+ 1
- 1
bot/commands/calc.py View File

@@ -12,7 +12,7 @@ class Command(BaseCommand):

def process(self, data):
if not data.args:
self.connection.reply(data, "What do you want me to calculate?")
self.connection.reply(data, "what do you want me to calculate?")
return

query = ' '.join(data.args)


+ 1
- 1
bot/commands/help.py View File

@@ -29,7 +29,7 @@ class Command(BaseCommand):

# Create a dummy message to test which commands pick up the user's
# input:
dummy = Data("PRIVMSG #fake-channel :Fake messsage!".split())
dummy = Data(":foo!bar@example.com PRIVMSG #channel :msg!".split())
dummy.command = command.lower()
dummy.is_command = True



+ 96
- 0
tests/support.py View File

@@ -0,0 +1,96 @@
# -*- coding: utf-8 -*-

"""
EarwigBot's Unit Test Support

This module provides some support code for unit tests.

Importing this module will "fix" your path so that EarwigBot code from bot/ can
be imported normally.

CommandTestCase is a subclass of unittest.TestCase that provides setUp() for
creating a fake connection and some other helpful methods. It uses
FakeConnection, a subclass of classes.Connection, but with an internal string
instead of a socket for data.
"""

from os import path
import re
import sys
from unittest import TestCase

root_dir = path.split(path.dirname(path.abspath(__file__)))[0]
code_dir = path.join(root_dir, "bot")
sys.path.insert(0, code_dir)

from classes import Connection, Data

class CommandTestCase(TestCase):
re_sender = re.compile(":(.*?)!(.*?)@(.*?)\Z")

def setUp(self, command):
self.connection = FakeConnection()
self.connection.connect()
self.command = command(self.connection)

def get_single(self):
data = self.connection.get().split("\n")
line = data.pop(0)
for remaining in data[1:]:
self.connection.send(remaining)
return line

def assertSent(self, msg):
line = self.get_single()
self.assertEqual(line, msg)

def assertSentIn(self, msgs):
line = self.get_single()
self.assertIn(line, msgs)

def assertSaid(self, msg):
self.assertSent("PRIVMSG #channel :{0}".format(msg))

def assertSaidIn(self, msgs):
msgs = ["PRIVMSG #channel :{0}".format(msg) for msg in msgs]
self.assertSentIn(msgs)

def assertReply(self, msg):
self.assertSaid("\x02Foo\x0F: {0}".format(msg))

def assertReplyIn(self, msgs):
msgs = ["\x02Foo\x0F: {0}".format(msg) for msg in msgs]
self.assertSaidIn(msgs)

def maker(self, line, chan, msg=None):
data = Data(line)
data.nick, data.ident, data.host = self.re_sender.findall(line[0])[0]
if msg is not None:
data.msg = msg
data.chan = chan
data.parse_args()
return data

def make_msg(self, command, *args):
line = ":Foo!bar@example.com PRIVMSG #channel :!{0}".format(command)
line = line.strip().split()
line.extend(args)
return self.maker(line, line[2], " ".join(line[3:])[1:])

def make_join(self):
line = ":Foo!bar@example.com JOIN :#channel".strip().split()
return self.maker(line, line[2][1:])

class FakeConnection(Connection):
def connect(self):
self._buffer = ""

def close(self):
pass

def get(self, size=4096):
data, self._buffer = self._buffer, ""
return data

def send(self, msg):
self._buffer += msg + "\n"

+ 77
- 0
tests/test_blowfish.py View File

@@ -0,0 +1,77 @@
# -*- coding: utf-8 -*-

import unittest
import random
import string

import support
import blowfish

class TestBlowfish(unittest.TestCase):

def test_key_sizes(self):
b = blowfish.Blowfish
e = blowfish.KeyLengthError

self.assertRaisesRegexp(e, "no key given", b, None)
self.assertRaisesRegexp(e, "no key given", b, "")
self.assertRaisesRegexp(e, "at least", b, " " * 3)
self.assertRaisesRegexp(e, "at least", b, "1234567")
self.assertRaisesRegexp(e, "less than", b, " " * 57)
self.assertRaisesRegexp(e, "less than", b, "x" * 60)
self.assertRaisesRegexp(e, "less than", b, "1" * 128)

b("These keys should be valid!")
b("'!\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'")
b(" " * 8)
b(" " * 56)

def test_symmetry(self):
def _test_symmetry():
key_length = random.randint(8, 56)
msg_length = random.randint(0, 4096)
key = "".join([random.choice(chars) for i in xrange(key_length)])
msg = "".join([random.choice(chars) for i in xrange(msg_length)])
enc = blowfish.encrypt(key, msg)
dec = blowfish.decrypt(key, enc)
self.assertEqual(dec, msg)

chars = string.letters + string.digits + string.punctuation
for i in xrange(8):
_test_symmetry()

def test_encryption(self):
tests = [
("example_key", "Hello, I'm a message!", "8411a21574431176cdff9a549d27962c616014a9fe2a1fe3b0c7a823e8a1e635"),
("another random key", "Another random message! :(", "2cdcdf4e53145897ed9d4cc2433aa4bf59b087b14d0ac76a13eff12dec00e60c40857109da3c7bc4"),
("HEY LET'S TRY |°|_J|\|C7|_J/-\\710|\|", "Yes, that was my fail attempt at 1337SP33K >_>", "d4901c7c0956da3b9507cd81cd3c880d7cda25ec6c5336deb9280ce67c099eeddf7c7e052f3a946afbd92c32ae0ab8dbdd875bc5a3f0d686")
]

for test in tests:
self.assertEquals(blowfish.encrypt(test[0], test[1]), test[2])

def test_decryption(self):
tests = [
("blah blah blah", "ab35274c66bb8b3b03c9bd26ab477f3de06857e1d369ad35", "Blah, blah, blah!"),
("random key", "eb2fe950c5c12bca9534ffdd27631f33d3e4bcae53a634b4aaa09f9fe14c4386", "Random message as well!"),
("Okay, now I'm just desperate", "0da74e1cec41e8323da93d0c05bcf3919084130cef93021991da174fd97f8e1c9b125ed5263b41a8", "Unit testing is SO FUN ISN'T IT.")
]

for test in tests:
self.assertEquals(blowfish.decrypt(test[0], test[1]), test[2])

def test_decryption_exceptions(self):
d = blowfish.decrypt
e = blowfish.BlowfishError

e1 = "could not be decoded"
e2 = "cannot be broken into 8-byte blocks"
e3 = "key is incorrect"

self.assertRaisesRegexp(e, e1, d, "some_key", "arr!")
self.assertRaisesRegexp(e, e2, d, "some_key", "abcd")
self.assertRaisesRegexp(e, e3, d, "some_key", "abcdabcdabcdabcd")

if __name__ == "__main__":
unittest.main(verbosity=2)

+ 39
- 0
tests/test_calc.py View File

@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-

import unittest

import support
from commands.calc import Command

class TestCalc(support.CommandTestCase):

def setUp(self):
super(TestCalc, self).setUp(Command)

def test_check(self):
self.assertFalse(self.command.check(self.make_msg("bloop")))
self.assertFalse(self.command.check(self.make_join()))

self.assertTrue(self.command.check(self.make_msg("calc")))
self.assertTrue(self.command.check(self.make_msg("CALC", "foo")))

def test_ignore_empty(self):
self.command.process(self.make_msg("calc"))
self.assertReply("what do you want me to calculate?")

def test_maths(self):
tests = [
("2 + 2", "2 + 2 = 4"),
("13 * 5", "13 * 5 = 65"),
("80 / 42", "80 / 42 = 40/21 (approx. 1.9047619047619047)"),
("2/0", "2/0 = undef"),
("π", "π = 3.141592653589793238"),
]

for test in tests:
q = test[0].strip().split()
self.command.process(self.make_msg("calc", *q))
self.assertReply(test[1])

if __name__ == "__main__":
unittest.main(verbosity=2)

+ 29
- 0
tests/test_test.py View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-

import unittest

import support
from commands.test import Command

class TestTest(support.CommandTestCase):

def setUp(self):
super(TestTest, self).setUp(Command)

def test_check(self):
self.assertFalse(self.command.check(self.make_msg("bloop")))
self.assertFalse(self.command.check(self.make_join()))

self.assertTrue(self.command.check(self.make_msg("test")))
self.assertTrue(self.command.check(self.make_msg("TEST", "foo")))

def test_process(self):
def _test():
self.command.process(self.make_msg("test"))
self.assertSaidIn(["Hey \x02Foo\x0F!", "'sup \x02Foo\x0F?"])

for i in xrange(64):
_test()

if __name__ == "__main__":
unittest.main(verbosity=2)

Loading…
Cancel
Save