Browse Source

Merge branch 'feature/tests-framework' into develop

tags/v0.1^2
Ben Kurtovic 13 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): def decrypt(key, cyphertext):
"""Decrypt the result of encrypt() using the original key, or raise """Decrypt the result of encrypt() using the original key, or raise
IncorrectKeyError(). If the cyphertext is malformed, raise
BadCyphertextError()."""
DecryptionError()."""
cypher = Blowfish(key) cypher = Blowfish(key)


try: try:


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

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


def process(self, data): def process(self, data):
if not data.args: 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 return


query = ' '.join(data.args) 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 # Create a dummy message to test which commands pick up the user's
# input: # input:
dummy = Data("PRIVMSG #fake-channel :Fake messsage!".split())
dummy = Data(":foo!bar@example.com PRIVMSG #channel :msg!".split())
dummy.command = command.lower() dummy.command = command.lower()
dummy.is_command = True 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