#                Perforce Defect Tracking Integration Project
#                 <http://www.ravenbrook.com/project/p4dti/>
#
#          TEST_CHECK_CONFIG.PY -- UNIT TEST FOR CHECK_CONFIG MODULE
#
#                 Gareth Rees, Ravenbrook Limited, 2001-03-14
#
#
# 1. INTRODUCTION
#
# This module defines a set of unit tests for the check_config 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 check_config
import p4dti_unittest
import unittest


# 2. TEST CASES


# 2.1. Passing and failing simple checks
#
# This test case has a table of values together with the checks which each
# value is supposed to pass.  The value is given to each checker function in
# turn and the result compared with the expectation in the table.

class fns(p4dti_unittest.TestCase):

    # The 'codes' table maps a code letter to a checking function in the
    # check_config module.
    codes = { 'b': check_config.check_bool,
              'd': check_config.check_date,
              'e': check_config.check_email,
              'f': check_config.check_function,
              'h': check_config.check_host,
              'i': check_config.check_int,
              's': check_config.check_string,
              'S': check_config.check_string_or_none,
              'I': check_config.check_identifier,
              'c': check_config.check_changelist_url,
              'j': check_config.check_job_url,
              }

    # The 'data' table is a list of pairs (codes, value), where 'codes' is a
    # list of code letters indicating the checking functions that the value
    # will pass (other checking functions will fail).
    data = [ ( "b     i    ", 0 ),
             ( "b     i    ", 1 ),
             ( " c   h   sS", "http://www.foo.bar/?%%3a+%%%d%%+%%3d" ),
             ( " c   h   sS", "%d" ),
             ( "     h  jsS", "http://www.foo.bar/?%%%%2b+%s+%%" ),
             ( "     h  jsS", "%s" ),
             ( " c      j S", None ),
             ( "  d  h   sS", "2001-12-01 23:00:59" ),
             ( "  d  h   sS", "1971-01-31 00:59:00" ),
             ( "   e h   sS", "gdr@ravenbrook.com" ),
             ( "   e h   sS", "gdr&rb+foo/bar/baz@xyz.invalid" ),
             ( "   e h   sS", "gdr!foo!bar@ravenbrook" ),
             ( "   e h   sS", "foo.bar@foo.bar.baz.quux.spong" ),
             ( "   e h   sS", "!#$%&'*+-/0123456789=?AZ^_`az{|}@invalid" ),
             ( "    f      ", (lambda (foo): None) ),
             ( "     h I sS", "abcdefg_0123456" ),
             ( "     h I sS", "abcdefg" ),
             ( "     h I sS", "_ABCDEFGHIJKLMNOPQRSTUVWXYZ01234" ),
             ( "     h I sS", "_abcdefghijklmnopqrstuvwxyz56789" ),
             ( "     h I sS", "_" ),
             ( "     h I sS", "M" ),
             ( "     h I sS", "A0Z" ),
             ( "     h   sS", "www.ravenbrook.com" ),
             ( "     h   sS", "public.perforce.com" ),
             ( "     h   sS", "gdr@foo@com" ),
             ( "     h   sS", "gdr@" ),
             ( "     h   sS", "gdr.ravenbrook.com" ),
             ( "     h   sS", "foo;bar@foo.com" ),
             ( "     h   sS", "foo,bar@baz.com>" ),
             ( "     h   sS", "abc@.foo.com" ),
             ( "     h   sS", "abc.@foo.com" ),
             ( "     h   sS", "@foo.com" ),
             ( "     h   sS", "@" ),
             ( "     h   sS", "<foo@bar.com>" ),
             ( "     h   sS", "9_" ),
             ( "     h   sS", "9_" ),
             ( "     h   sS", "9" ),
             ( "     h   sS", "5abc" ),
             ( "     h   sS", "2001/03/14 13:59:42" ),
             ( "     h   sS", "2001-3-4 3:59:42" ),
             ( "     h   sS", "2001-03-14T13:59:42Z" ),
             ( "     h   sS", "1971-13-01 00:00:00" ),
             ( "     h   sS", "1971-01-32 00:00:00" ),
             ( "     h   sS", "1971-01-01 24:00:00" ),
             ( "     h   sS", "1971-01-01 00:60:00" ),
             ( "     h   sS", "1971-01-01 00:00:60" ),
             ( "     h   sS", "1971-01-00 00:00:00" ),
             ( "     h   sS", "1971-00-01 00:00:00" ),
             ( "     h   sS", "0abc" ),
             ( "     h   sS", "01-03-14 13:59:42" ),
             ( "     h   sS", "" ),
             ( "     h   sS", "http://www.foo.bar/%d/%" ),
             ( "     h   sS", "http://%s/%x/%%%" ),
             ( "      i    ", 99 ),
             ( "      i    ", -1 ),
             ]

    def runTest(self):
        "Checking functions (test_check_config.fns)"
        for (codes, value) in self.data:
            for (code, checker) in self.codes.items():
                try:
                    checker(value, 'value')
                except check_config.error:
                    if code in codes:
                        self.addFailure("Checker %s on '%s' failed "
                                        "(should have passed)."
                                        % (checker, value))
                else:
                    if code not in codes:
                        self.addFailure("Checker %s on '%s' passed "
                                        "(should have failed)."
                                        % (checker, value))


# 3. RUNNING THE TESTS

def tests():
    suite = unittest.TestSuite()
    suite.addTest(fns())
    return suite

if __name__ == "__main__":
    unittest.main(defaultTest="tests")


# A. REFERENCES
#
# [PyUnit] "PyUnit - a unit testing framework for Python"; Steve Purcell;
# <http://pyunit.sourceforge.net/>.
#
#
# B. DOCUMENT HISTORY
#
# 2001-03-14 GDR Created.
#
# 2001-03-24 GDR Added tests for check_changelist_url and check_identfier.
#
# 2001-04-24 GDR Use p4dti_unittest to collect many failures per test case.
#
# 2001-07-09 NB Added check_job_url test.
#
#
# C. COPYRIGHT AND LICENCE
#
# 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/1.1/test/test_check_config.py#4 $
