10a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#!/usr/bin/env python
20a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
30a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#-----------------------------------------------------------------------
40a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# A test suite for the table interface built on bsddb.db
50a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#-----------------------------------------------------------------------
60a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
70a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Copyright (C) 2000, 2001 by Autonomous Zone Industries
80a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# Copyright (C) 2002 Gregory P. Smith
90a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# March 20, 2000
110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# License:      This is free software.  You may use this software for any
130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#               purpose including modification/redistribution, so long as
140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#               this header remains intact and that you do not claim any
150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#               rights of ownership or authorship of this software.  This
160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#               software has been tested, but no warranty is expressed or
170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#               implied.
180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#   --  Gregory P. Smith <greg@krypto.org>
200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#
210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao# $Id$
220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
230a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport os, re, sys
240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
250a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoif sys.version_info[0] < 3 :
260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    try:
270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        import cPickle
280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        pickle = cPickle
290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    except ImportError:
300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        import pickle
310a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoelse :
320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    import pickle
330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
340a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport unittest
350a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom test_all import db, dbtables, test_support, verbose, \
360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        get_new_environment_path, get_new_database_path
370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao#----------------------------------------------------------------------
390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
400a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass TableDBTestCase(unittest.TestCase):
410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    db_name = 'test-table.db'
420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def setUp(self):
440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        import sys
450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if sys.version_info[0] >= 3 :
460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            from test_all import do_proxy_db_py3k
470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self._flag_proxy_db_py3k = do_proxy_db_py3k(False)
480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.testHomeDir = get_new_environment_path()
500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb = dbtables.bsdTableDB(
510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            filename='tabletest.db', dbhome=self.testHomeDir, create=1)
520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def tearDown(self):
540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.close()
550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        import sys
560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if sys.version_info[0] >= 3 :
570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            from test_all import do_proxy_db_py3k
580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            do_proxy_db_py3k(self._flag_proxy_db_py3k)
590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        test_support.rmtree(self.testHomeDir)
600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test01(self):
620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        tabname = "test01"
630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        colname = 'cool numbers'
640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb.Drop(tabname)
660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except dbtables.TableDBError:
670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            pass
680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.CreateTable(tabname, [colname])
690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        import sys
700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if sys.version_info[0] < 3 :
710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb.Insert(tabname, {colname: pickle.dumps(3.14159, 1)})
720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else :
730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb.Insert(tabname, {colname: pickle.dumps(3.14159,
740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                1).decode("iso8859-1")})  # 8 bits
750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if verbose:
770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb._db_print()
780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        values = self.tdb.Select(
800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            tabname, [colname], conditions={colname: None})
810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        import sys
830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if sys.version_info[0] < 3 :
840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            colval = pickle.loads(values[0][colname])
850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else :
860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            colval = pickle.loads(bytes(values[0][colname], "iso8859-1"))
870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertTrue(colval > 3.141)
880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertTrue(colval < 3.142)
890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test02(self):
920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        tabname = "test02"
930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        col0 = 'coolness factor'
940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        col1 = 'but can it fly?'
950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        col2 = 'Species'
960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        import sys
980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if sys.version_info[0] < 3 :
990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            testinfo = [
1000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                {col0: pickle.dumps(8, 1), col1: 'no', col2: 'Penguin'},
1010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                {col0: pickle.dumps(-1, 1), col1: 'no', col2: 'Turkey'},
1020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                {col0: pickle.dumps(9, 1), col1: 'yes', col2: 'SR-71A Blackbird'}
1030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ]
1040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else :
1050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            testinfo = [
1060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                {col0: pickle.dumps(8, 1).decode("iso8859-1"),
1070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    col1: 'no', col2: 'Penguin'},
1080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                {col0: pickle.dumps(-1, 1).decode("iso8859-1"),
1090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    col1: 'no', col2: 'Turkey'},
1100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                {col0: pickle.dumps(9, 1).decode("iso8859-1"),
1110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    col1: 'yes', col2: 'SR-71A Blackbird'}
1120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            ]
1130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
1150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb.Drop(tabname)
1160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except dbtables.TableDBError:
1170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            pass
1180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.CreateTable(tabname, [col0, col1, col2])
1190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        for row in testinfo :
1200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb.Insert(tabname, row)
1210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        import sys
1230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if sys.version_info[0] < 3 :
1240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            values = self.tdb.Select(tabname, [col2],
1250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                conditions={col0: lambda x: pickle.loads(x) >= 8})
1260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else :
1270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            values = self.tdb.Select(tabname, [col2],
1280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                conditions={col0: lambda x:
1290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    pickle.loads(bytes(x, "iso8859-1")) >= 8})
1300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(len(values), 2)
1320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if values[0]['Species'] == 'Penguin' :
1330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.assertEqual(values[1]['Species'], 'SR-71A Blackbird')
1340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        elif values[0]['Species'] == 'SR-71A Blackbird' :
1350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.assertEqual(values[1]['Species'], 'Penguin')
1360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else :
1370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if verbose:
1380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                print "values= %r" % (values,)
1390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise RuntimeError("Wrong values returned!")
1400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test03(self):
1420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        tabname = "test03"
1430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
1440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb.Drop(tabname)
1450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except dbtables.TableDBError:
1460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            pass
1470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if verbose:
1480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            print '...before CreateTable...'
1490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb._db_print()
1500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e'])
1510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if verbose:
1520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            print '...after CreateTable...'
1530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb._db_print()
1540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Drop(tabname)
1550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if verbose:
1560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            print '...after Drop...'
1570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb._db_print()
1580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e'])
1590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
1610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb.Insert(tabname,
1620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                            {'a': "",
1630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                             'e': pickle.dumps([{4:5, 6:7}, 'foo'], 1),
1640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                             'f': "Zero"})
1650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.fail('Expected an exception')
1660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except dbtables.TableDBError:
1670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            pass
1680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
1700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb.Select(tabname, [], conditions={'foo': '123'})
1710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.fail('Expected an exception')
1720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except dbtables.TableDBError:
1730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            pass
1740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Insert(tabname,
1760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        {'a': '42',
1770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                         'b': "bad",
1780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                         'c': "meep",
1790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                         'e': 'Fuzzy wuzzy was a bear'})
1800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Insert(tabname,
1810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        {'a': '581750',
1820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                         'b': "good",
1830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                         'd': "bla",
1840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                         'c': "black",
1850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                         'e': 'fuzzy was here'})
1860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Insert(tabname,
1870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        {'a': '800000',
1880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                         'b': "good",
1890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                         'd': "bla",
1900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                         'c': "black",
1910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                         'e': 'Fuzzy wuzzy is a bear'})
1920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if verbose:
1940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb._db_print()
1950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # this should return two rows
1970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        values = self.tdb.Select(tabname, ['b', 'a', 'd'],
1980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            conditions={'e': re.compile('wuzzy').search,
1990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        'a': re.compile('^[0-9]+$').match})
2000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(len(values), 2)
2010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # now lets delete one of them and try again
2030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Delete(tabname, conditions={'b': dbtables.ExactCond('good')})
2040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        values = self.tdb.Select(
2050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            tabname, ['a', 'd', 'b'],
2060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            conditions={'e': dbtables.PrefixCond('Fuzzy')})
2070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(len(values), 1)
2080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(values[0]['d'], None)
2090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        values = self.tdb.Select(tabname, ['b'],
2110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            conditions={'c': lambda c: c == 'meep'})
2120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(len(values), 1)
2130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(values[0]['b'], "bad")
2140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test04_MultiCondSelect(self):
2170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        tabname = "test04_MultiCondSelect"
2180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
2190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb.Drop(tabname)
2200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except dbtables.TableDBError:
2210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            pass
2220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e'])
2230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
2250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb.Insert(tabname,
2260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                            {'a': "",
2270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                             'e': pickle.dumps([{4:5, 6:7}, 'foo'], 1),
2280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                             'f': "Zero"})
2290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.fail('Expected an exception')
2300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except dbtables.TableDBError:
2310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            pass
2320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Insert(tabname, {'a': "A", 'b': "B", 'c': "C", 'd': "D",
2340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'e': "E"})
2350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Insert(tabname, {'a': "-A", 'b': "-B", 'c': "-C", 'd': "-D",
2360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'e': "-E"})
2370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Insert(tabname, {'a': "A-", 'b': "B-", 'c': "C-", 'd': "D-",
2380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'e': "E-"})
2390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if verbose:
2410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb._db_print()
2420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # This select should return 0 rows.  it is designed to test
2440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # the bug identified and fixed in sourceforge bug # 590449
2450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # (Big Thanks to "Rob Tillotson (n9mtb)" for tracking this down
2460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # and supplying a fix!!  This one caused many headaches to say
2470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # the least...)
2480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        values = self.tdb.Select(tabname, ['b', 'a', 'd'],
2490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            conditions={'e': dbtables.ExactCond('E'),
2500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        'a': dbtables.ExactCond('A'),
2510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        'd': dbtables.PrefixCond('-')
2520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                       } )
2530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(len(values), 0, values)
2540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_CreateOrExtend(self):
2570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        tabname = "test_CreateOrExtend"
2580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.CreateOrExtendTable(
2600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            tabname, ['name', 'taste', 'filling', 'alcohol content', 'price'])
2610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
2620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb.Insert(tabname,
2630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                            {'taste': 'crap',
2640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                             'filling': 'no',
2650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                             'is it Guinness?': 'no'})
2660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.fail("Insert should've failed due to bad column name")
2670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except:
2680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            pass
2690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.CreateOrExtendTable(tabname,
2700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                     ['name', 'taste', 'is it Guinness?'])
2710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # these should both succeed as the table should contain the union of both sets of columns.
2730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Insert(tabname, {'taste': 'crap', 'filling': 'no',
2740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'is it Guinness?': 'no'})
2750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Insert(tabname, {'taste': 'great', 'filling': 'yes',
2760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'is it Guinness?': 'yes',
2770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'name': 'Guinness'})
2780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_CondObjs(self):
2810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        tabname = "test_CondObjs"
2820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.CreateTable(tabname, ['a', 'b', 'c', 'd', 'e', 'p'])
2840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Insert(tabname, {'a': "the letter A",
2860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'b': "the letter B",
2870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'c': "is for cookie"})
2880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Insert(tabname, {'a': "is for aardvark",
2890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'e': "the letter E",
2900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'c': "is for cookie",
2910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'd': "is for dog"})
2920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Insert(tabname, {'a': "the letter A",
2930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'e': "the letter E",
2940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'c': "is for cookie",
2950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'p': "is for Python"})
2960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
2970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        values = self.tdb.Select(
2980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            tabname, ['p', 'e'],
2990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            conditions={'e': dbtables.PrefixCond('the l')})
3000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(len(values), 2, values)
3010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(values[0]['e'], values[1]['e'], values)
3020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertNotEqual(values[0]['p'], values[1]['p'], values)
3030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        values = self.tdb.Select(
3050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            tabname, ['d', 'a'],
3060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            conditions={'a': dbtables.LikeCond('%aardvark%')})
3070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(len(values), 1, values)
3080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(values[0]['d'], "is for dog", values)
3090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(values[0]['a'], "is for aardvark", values)
3100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        values = self.tdb.Select(tabname, None,
3120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                 {'b': dbtables.Cond(),
3130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'e':dbtables.LikeCond('%letter%'),
3140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'a':dbtables.PrefixCond('is'),
3150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'd':dbtables.ExactCond('is for dog'),
3160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'c':dbtables.PrefixCond('is for'),
3170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'p':lambda s: not s})
3180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(len(values), 1, values)
3190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(values[0]['d'], "is for dog", values)
3200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(values[0]['a'], "is for aardvark", values)
3210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_Delete(self):
3230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        tabname = "test_Delete"
3240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.CreateTable(tabname, ['x', 'y', 'z'])
3250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # prior to 2001-05-09 there was a bug where Delete() would
3270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # fail if it encountered any rows that did not have values in
3280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # every column.
3290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # Hunted and Squashed by <Donwulff> (Jukka Santala - donwulff@nic.fi)
3300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Insert(tabname, {'x': 'X1', 'y':'Y1'})
3310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Insert(tabname, {'x': 'X2', 'y':'Y2', 'z': 'Z2'})
3320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Delete(tabname, conditions={'x': dbtables.PrefixCond('X')})
3340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        values = self.tdb.Select(tabname, ['y'],
3350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                 conditions={'x': dbtables.PrefixCond('X')})
3360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(len(values), 0)
3370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def test_Modify(self):
3390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        tabname = "test_Modify"
3400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.CreateTable(tabname, ['Name', 'Type', 'Access'])
3410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Insert(tabname, {'Name': 'Index to MP3 files.doc',
3430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                                  'Type': 'Word', 'Access': '8'})
3440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Insert(tabname, {'Name': 'Nifty.MP3', 'Access': '1'})
3450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Insert(tabname, {'Type': 'Unknown', 'Access': '0'})
3460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def set_type(type):
3480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if type is None:
3490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                return 'MP3'
3500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return type
3510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def increment_access(count):
3530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return str(int(count)+1)
3540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        def remove_value(value):
3560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return None
3570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Modify(tabname,
3590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        conditions={'Access': dbtables.ExactCond('0')},
3600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        mappings={'Access': remove_value})
3610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Modify(tabname,
3620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        conditions={'Name': dbtables.LikeCond('%MP3%')},
3630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        mappings={'Type': set_type})
3640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.tdb.Modify(tabname,
3650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        conditions={'Name': dbtables.LikeCond('%')},
3660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        mappings={'Access': increment_access})
3670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
3690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.tdb.Modify(tabname,
3700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                            conditions={'Name': dbtables.LikeCond('%')},
3710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                            mappings={'Access': 'What is your quest?'})
3720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except TypeError:
3730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            # success, the string value in mappings isn't callable
3740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            pass
3750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
3760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            raise RuntimeError, "why was TypeError not raised for bad callable?"
3770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # Delete key in select conditions
3790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        values = self.tdb.Select(
3800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            tabname, None,
3810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            conditions={'Type': dbtables.ExactCond('Unknown')})
3820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(len(values), 1, values)
3830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(values[0]['Name'], None, values)
3840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(values[0]['Access'], None, values)
3850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # Modify value by select conditions
3870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        values = self.tdb.Select(
3880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            tabname, None,
3890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            conditions={'Name': dbtables.ExactCond('Nifty.MP3')})
3900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(len(values), 1, values)
3910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(values[0]['Type'], "MP3", values)
3920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(values[0]['Access'], "2", values)
3930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
3940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        # Make sure change applied only to select conditions
3950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        values = self.tdb.Select(
3960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            tabname, None, conditions={'Name': dbtables.LikeCond('%doc%')})
3970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(len(values), 1, values)
3980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(values[0]['Type'], "Word", values)
3990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.assertEqual(values[0]['Access'], "9", values)
4000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4020a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef test_suite():
4030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    suite = unittest.TestSuite()
4040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    suite.addTest(unittest.makeSuite(TableDBTestCase))
4050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    return suite
4060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
4080a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoif __name__ == '__main__':
4090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    unittest.main(defaultTest='test_suite')
410