# Perforce Defect Tracking Integration Project
#
#
# TEST_MESSAGE.PY -- UNIT TESTS FOR MESSAGE MODULE
#
# Gareth Rees, Ravenbrook Limited, 2001-03-13
#
#
# 1. INTRODUCTION
#
# This module defines a set of unit tests for the message module.
#
# It uses the PyUnit unit test framework [PyUnit].
#
# The intended readership is project developers.
#
# This document is not confidential.
import os
import sys
p4dti_path = os.path.join(os.getcwd(), os.pardir, 'code', 'replicator')
if p4dti_path not in sys.path:
sys.path.append(p4dti_path)
import message
import p4dti_unittest
import string
import unittest
import whrandom
# 2. TEST CASES
# 2.1. Message creation and conversion
#
# Test that messages can be created and converted to a string.
success_cases = [
( 1, "Test 1", message.DEBUG, "Foo", "(Foo-11) Test 1" ),
( 22, "Test 2", message.INFO, "XYZ", "(XYZ-226) Test 2" ),
( 333, "Test 3", message.NOTICE, "", "(3337) Test 3" ),
( 4444, "Test 4", message.WARNING, "P", "(P-44447) Test 4" ),
( 12345, "Test 5", message.ERR, "%%%%", "(%%%%-123452) Test 5" ),
( 9999, "Test 6", message.CRIT, "%s%d", "(%s%d-99992) Test 6" ),
( 999, "Test 7", message.ALERT, "a", "(a-999X) Test 7" ),
( 0, "Test 8", message.EMERG, "", "(00) Test 8" ),
]
class create(p4dti_unittest.TestCase):
def runTest(self):
"Message creation and conversion (test_message.create)"
for case in success_cases:
(id, text, priority, product, expected) = case
msg = message.message(id, text, priority, product)
found = str(msg)
if expected != found:
self.addFailure("Case %s: expected '%s' but found '%s'."
% (case, expected, found))
# 2.2. Failure on message creation
#
# Test that attempts to create messages with bogus data fail.
failure_cases = [
( None, "Failure 1", message.EMERG, "Foo", AssertionError ),
( -1, "Failure 2", message.INFO, "XYZ", AssertionError ),
( 0, None, message.EMERG, "", AssertionError ),
( 999, "Failure 4", "message.CRIT", "Foo", AssertionError ),
( 56, "Failure 5", -1, "P4DTI", AssertionError ),
( 12345, "Failure 6", 100, "abcd", AssertionError ),
( 1234, "Failure 7", message.EMERG, 999, AssertionError ),
]
class fail(p4dti_unittest.TestCase):
def runTest(self):
"Creating messages with bogus data fails (test_message.fail)"
for case in failure_cases:
(id, text, priority, product, expected) = case
try:
message.message(id, text, priority, product)
except expected:
pass
else:
self.addFailure("Case %s: expected %s."
% (case, expected))
# 2.3. Message wrapping
#
# Test that wrapping to a number of columns works as expected.
class wrap(p4dti_unittest.TestCase):
def runTest(self):
"Message wrapping (test_message.wrap)"
# On trial 0, try cases where no word is longer than the number
# of columns. On trial 1, try cases where some words are longer
# than the number of columns.
for trial in range(2):
columns = 1
while columns < 1000:
nwords = 10 + whrandom.randint(0, columns)
def word(_, c=columns, t=trial):
return (string.letters[whrandom.randint(0,25)]
* whrandom.randint(1, c * (t + 1)))
text = string.join(map(word, range(nwords)), ' ')
msg = message.message(0, text, message.DEBUG, "")
expected = str(msg)
wrapped = msg.wrap(columns)
lines = string.split(wrapped, '\n')
if lines[0] == '(00)':
found = (lines[0] + ' '
+ string.join(lines[1:], ' '))
else:
found = string.join(lines, ' ')
for l in range(0,len(lines)):
# On trial 0 each line must fit in the columns,
# since no word was longer than columns.
if (trial == 0 and (l > 0 or columns > 4)
and len(lines[l]) > columns):
self.addFailure("Wrapping to %d columns, line "
"%d has length %d (%s)."
% (columns, l, len(lines[l]),
lines))
# Lines longer than the columns consist of a single
# word.
if (len(lines[l]) > columns
and string.find(lines[l], ' ') != -1):
self.addFailure("Wrapping to %d columns, line "
"%d has a space (%s)."
% (columns, l, lines))
# No line can be extended by adjoining the first
# word from the following line without making it go
# over the number of columns.
if (l + 1 < len(lines)
and ((len(lines[l]) + 1 + (l == 0) +
len(string.split(lines[l+1],' ')[0]))
<= columns)):
self.addFailure("Wrapping to %d columns, line "
"%d could have an extra word "
"in it (%s)."
% (columns, l, lines))
if expected != found:
self.addFailure("Wrapping to %d columns:\n"
"Expected: %s\nFound: %s\n"
"Wrapped: %s."
% (columns, expected, found,
`wrapped`))
columns = columns * 2 + whrandom.randint(0,1)
# 2.4. Message factory
class factory(unittest.TestCase):
def runTest(self):
"Message factories (test_message.factory)"
products = ['foo', 'bar', 'baz']
for n in range(8):
p = products[n % 3]
f = message.factory(n, p)
text = "Test %d" % n
m = f.new(n, text)
assert m.id == n
assert m.priority == n
assert m.product == p
assert m.text == text
assert str(m) == "(%s-%d%d) %s" % (p, n, n, text)
# 2.5. Catalog factory
class catalog(unittest.TestCase):
catalog = {
1: (message.CRIT, "%s"),
23: (message.ERR, "%d"),
34: (message.INFO, "%d%d"),
45: (message.DEBUG, "%d%s"),
}
product = 'foo'
tests = [
(1, "xyz", message.CRIT, "(foo-11) xyz"),
(23, 19, message.ERR, "(foo-237) 19"),
(34, (100,200), message.INFO, "(foo-34X) 100200"),
(45, (9,'baz'), message.DEBUG, "(foo-452) 9baz"),
(23, 'baz', message.ERR, "(foo-00) Message 23 has format "
"string '%d' but arguments baz."),
(99, (), message.ERR, "(foo-00) No message with id '99' "
"(args = ())."),
]
def runTest(self):
"Catalog factories (test_message.catalog)"
f = message.catalog_factory(self.catalog, self.product)
for id, args, priority, expected in self.tests:
m = f.new(id, args)
assert isinstance(m, message.message)
assert str(m) == expected, ("Expected %s but found %s."
% (expected, str(m)))
assert m.priority == priority, ("Expected %d but found %d."
% (priority, m.priority))
# 3. RUNNING THE TESTS
def tests():
suite = unittest.TestSuite()
for t in [create, fail, wrap, factory, catalog]:
suite.addTest(t())
return suite
if __name__ == "__main__":
unittest.main(defaultTest="tests")
# A. REFERENCES
#
# [PyUnit] "PyUnit - a unit testing framework for Python"; Steve
# Purcell; .
#
#
# B. DOCUMENT HISTORY
#
# 2001-03-13 GDR Created.
#
# 2001-04-24 GDR Use p4dti_unittest to collect many failures per test
# case.
#
# 2001-12-05 GDR Test message factories and catalog factories.
#
#
# C. COPYRIGHT AND LICENSE
#
# This file is copyright (c) 2001 Perforce Software, Inc. All rights
# reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
#
#
# $Id: //info.ravenbrook.com/project/p4dti/version/2.1/test/test_message.py#1 $