# 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 $