def setUp(self): unittest.TestCase.setUp(self) server = gnats.Server('somehost') conn = FakeServerConnectionForDB(server) self.db = Database(server, 'testdb', conn) self.db._validate = self.my_validate self.pr_in = '' self.validate_in = ''
class T03_EnumField(unittest.TestCase): """ EnumField tests """ def setUp(self): self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) self.enum = self.db.fields['enum-fld'] self.multi = self.db.fields['multienum-fld'] def tearDown(self): gnats.metadata_level = gnats.FULL_METADATA def test_1_values(self): """ values """ self.assertEqual(self.enum.values, ['cat1', 'cat2', 'cat3', 'cat4']) def test_2_sort_keys(self): """ sort_keys """ self.assertEqual(self.enum.sort_keys['cat1'], 0) self.assertEqual(self.multi.sort_keys['product2'], 1) def test_3_separators(self): """ separators """ self.assertEqual(self.multi.separators, ':|') def test_4_default_separator(self): """ default_separator """ self.assertEqual(self.multi.default_separator, ':') def test_5_list_values(self): """ list_values """ self.assertEqual(self.db.fields['scoped-enum-fld'].list_values(), ['open', 'analyzed', 'closed']) def test_06_values_dict(self): """ subfield dict values """ fld = self.db.fields['enum-fld'] self.assertEqual(len(fld.values), 4) self.assertEqual(len(fld.values_dict), 4) self.assertEqual(fld.values_dict['cat1'], {'owner': 'c12', 'group-owner': 'c15', 'group': 'c14', 'description': 'c11', 'notify': 'c13', 'category': 'cat1'}) def test_07_load_metadata(self): """ load_metadata method """ gnats.metadata_level = gnats.NO_ENUM_METADATA # "Refresh" the conn, so that metadata can run again self.conn = FakeServerConnectionForDB(self.server) self.db.last_config_time = 987 self.db._get_metadata(self.conn) enum = self.db.fields['enum-fld'] self.assertEqual(len(enum.values), 0) self.conn = FakeServerConnectionForDB(self.server) enum.load_enum_values(self.conn) self.assertEqual(len(enum.values), 4)
def setUp(self): unittest.TestCase.setUp(self) server = gnats.Server('somehost') conn = FakeServerConnectionForDB(server) self.db = Database(server, 'testdb', conn) self.db.validate_field = self.my_validate_field self.fname_in = [] self.pr_in = [] self.check_cr_in = [] self.vf_out = []
def test_03_minimal(self): """ MINIMAL_METADATA """ gnats.metadata_level = gnats.MINIMAL_METADATA db = Database(self.server, 'testdb', self.conn) self.assertEqual(db.name, 'testdb') self.assertEqual(db.description, '') self.assertEqual(db.builtin('number'), 'number') self.assertEqual(len(db.list_fields()), 8) self.assertEqual(len(db.initial_entry_fields), 0) self.assertEqual(db.fields['synopsis'].lcname, 'synopsis') self.assertEqual(db.fields['synopsis'].description, '') self.assertEqual(len(db.fields['enum-fld'].values), 0)
def test_01_full(self): """ FULL_METADATA """ gnats.metadata_level = gnats.FULL_METADATA db = Database(self.server, 'testdb', self.conn) self.assertEqual(db.name, 'testdb') self.assertEqual(db.description, 'Fake Database') self.assertEqual(len(db.list_fields()), 8) self.assertEqual(len(db.initial_entry_fields), 4) self.assertEqual(db.fields['synopsis'].lcname, 'synopsis') self.assertEqual(db.fields['synopsis'].name, 'Synopsis') self.assertEqual(db.fields['synopsis'].description, 'Synopsis field') self.assertEqual(db.fields['enum-fld'].values[0], 'cat1')
def test_05_refresh_false(self): """ refresh_metadata_automatically honored if False""" gnats.refresh_metadata_automatically = False db = Database(self.server, 'testdb', self.conn) def cb(dbx): cb.dbin = dbx cb.dbin = None db.post_metadata_callback = cb # "Refresh" the conn, so that metadata can run again self.conn = FakeServerConnectionForDB(self.server) db.last_config_time = 987 db.get_handle('user', 'pass', self.conn) self.assertEqual(cb.dbin, None)
def test_02_no_enum(self): """ NO_ENUM_METADATA """ gnats.metadata_level = gnats.NO_ENUM_METADATA db = Database(self.server, 'testdb', self.conn) self.assertEqual(db.name, 'testdb') self.assertEqual(db.description, 'Fake Database') self.assertEqual(len(db.list_fields()), 8) self.assertEqual(db.builtin('number'), 'number') self.assertRaises(GnatsException, db._validate, 1, 1) self.assertRaises(GnatsException, db.validate_field, 1, 1) self.assertEqual(len(db.initial_entry_fields), 4) self.assertEqual(db.fields['synopsis'].lcname, 'synopsis') self.assertEqual(db.fields['synopsis'].name, 'Synopsis') self.assertEqual(db.fields['synopsis'].description, 'Synopsis field') self.assertEqual(len(db.fields['enum-fld'].values), 0) self.assertRaises(GnatsException, db.fields['enum-fld'].list_values)
def setUp(self): unittest.TestCase.setUp(self) self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) self.dbh = self.db.get_handle('user', 'pass', self.conn) self.conn.rset = self.my_rset self.rset_called = False self.conn.qfmt = self.my_qfmt self.qfmt = '' self.conn.tqfmt = self.my_tqfmt self.tqfmt = '' self.tqfmt_fname = '' self.conn.quer = self.my_quer self.parse = False self.prnum = [] self.db.build_format = self.my_build_format self.fnames = [] self.bf_tfield = [] self.pr_fields = [] self.table_cols = [] self.dbh.old_get_pr_fields = self.dbh._get_pr_fields self.dbh._get_pr_fields = self.my_get_pr_fields self.vtc_cols = '' self.vtc_fnames = '' self.vtc_out = '' self.old_validate_table_columns = self.dbh._validate_table_columns self.dbh._validate_table_columns = self.my_validate_table_columns
def setUp(self): unittest.TestCase.setUp(self) self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) self.dbh = self.db.get_handle('user', 'pass', self.conn) self.db.unparse_pr = self.my_unparse_pr self.unp_in = {} self.conn.editaddr = self.my_editaddr self.edad_in = '' self.testval = None
def test_03_none(self): """ NO_METADATA """ gnats.metadata_level = gnats.NO_METADATA db = Database(self.server, 'testdb', self.conn) self.assertEqual(db.name, 'testdb') self.assertEqual(db.description, '') self.assertRaises(GnatsException, db.unparse_pr, 1) self.assertRaises(GnatsException, db.build_format, 1) self.assertRaises(GnatsException, db.builtin, 1) self.assertRaises(GnatsException, db.list_fields) self.assertEqual(len(db.initial_entry_fields), 0) self.assertEqual(len(db.fields), 0)
class T01_MetadataAndUtilityMethods(unittest.TestCase): """ Various internal and external utility methods. """ def setUp(self): unittest.TestCase.setUp(self) self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) self.dbh = self.db.get_handle('user', 'pass', self.conn) def test_01_conn(self): """ Connection """ self.assertEqual(self.dbh.conn, self.conn) def test_02_database(self): """ database """ self.assertEqual(self.dbh.database, self.db) def test_03_username(self): """ username """ self.assertEqual(self.dbh.username, 'user') def test_04_password(self): """ passwd """ self.assertEqual(self.dbh.passwd, 'pass') def test_05_access_level(self): """ access_level """ self.assertEqual(self.dbh.access_level, 'edit') def test_06_prnum_to_sortable_num(self): """ _prnum_to_sortable returns number given number """ self.assertEqual(self.dbh._prnum_to_sortable('1234'), 1234) def test_07_prnum_to_sortable_scoped(self): """ _prnum_to_sortable works for scoped numbers """ self.assertEqual(self.dbh._prnum_to_sortable('1234-1'), 1234001) def test_08_numeric_sortable(self): """ _numeric_sortable parses correctly """ self.assertEqual(self.dbh._numeric_sortable('8.5R1.3'), (8, 5, 1, 3)) self.assertEqual(self.dbh._numeric_sortable('1234, 5432'), (1234, 5432)) self.assertEqual(self.dbh._numeric_sortable('fred1'), (1,)) self.assertEqual(self.dbh._numeric_sortable('fred'), 'fred')
class T07_ValidatePR(unittest.TestCase): """ PR validation methods """ def setUp(self): unittest.TestCase.setUp(self) server = gnats.Server('somehost') conn = FakeServerConnectionForDB(server) self.db = Database(server, 'testdb', conn) self.db._validate = self.my_validate self.pr_in = '' self.validate_in = '' def my_validate(self, pr, validate): self.pr_in = pr self.validate_in = validate return 1 def test_01_validate_fields(self): """ validate_fields() """ self.db.validate_fields('pr', change_reasons=False) self.assertEqual(self.pr_in, 'pr') self.assertEqual(self.validate_in, 'fields') def test_02_validate_fields_cr(self): """ validate_fields() with change-reasons """ self.db.validate_fields('pr', change_reasons=True) self.assertEqual(self.pr_in, 'pr') self.assertEqual(self.validate_in, 'fields-cr') def test_03_validate_pr(self): """ validate_pr() """ self.db.validate_pr('pr') self.assertEqual(self.pr_in, 'pr') self.assertEqual(self.validate_in, 'all') def test_04_validate_initial(self): """ validate_initial() """ self.db.validate_initial('pr') self.assertEqual(self.pr_in, 'pr') self.assertEqual(self.validate_in, 'initial')
def setUp(self): unittest.TestCase.setUp(self) self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) self.dbh = self.db.get_handle('user', 'pass', self.conn) self.edit = self.dbh.edit_pr self.conn.edit = self.my_edit self.prnum_in = '' self.db.unparse_pr = self.my_unparse_pr self.unp_in = {} self.conn.editaddr = self.my_editaddr self.addr_in = '' self.dbh.get_pr = self.my_get_pr # Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld self.curr_pr = {'synopsis': 'foo bar', 'enum-fld': 'sw-tools', 'multienum-fld': 'tools', 'multitext-fld': 'a value', 'identifier': [(1, {'scoped-enum-fld': 'open'})],}
def get_database(self, dbname, conn=None): """ Get a Database object. If a connection is supplied, it will be used to fetch the db metadata. """ global connection conn = connection if not dbname in self._database_names: self._dbls_time = 0 self.list_databases(conn) if not dbname in self._database_names: raise GnatsException( "Database '%s' not found on server %s:%s" % (dbname, self.host, self.port)) if self._databases.has_key(dbname): return self._databases[dbname] else: db = Database(self, dbname, self.get_connection(conn)) self._databases[dbname] = db return db
def setUp(self): unittest.TestCase.setUp(self) self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) self.dbh = self.db.get_handle('user', 'pass', self.conn) self.conn.rset = self.my_rset self.rset_called = False self.conn.expr = self.my_expr self.expr = '' self.conn.qfmt = self.my_qfmt self.qfmt = '' self.conn.quer = self.my_quer self.tqfmt = '' self.tqfmt_fname = '' self.conn.tqfmt = self.my_tqfmt self.db.build_format = self.my_build_format self.bf_fnames = [] self.bf_tfield = [] self.parse = False self.quer_out = [] self.test_param = ''
def setUp(self): self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) self.tfield = self.db.fields['change-log']
class T04_DatabaseMethods(unittest.TestCase): """ Test Database utility methods """ def setUp(self): self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) def test_01_get_handle(self): """ get_handle returns DatabaseHandle """ self.assertTrue( isinstance(self.db.get_handle('user', 'pass', self.conn), DatabaseHandle)) def test_02_get_handle_doesnt_refresh(self): """ get_handle uses cached metadata when not expired """ # Change the dbdesc method to return something we can check self.conn.dbdesc = lambda __: 'changed database' self.db.get_handle('user', 'pass', self.conn) self.assertNotEquals(self.db.description, 'changed database') def test_03_get_handle_refreshes(self): """ get_handle refreshes metadata when expired """ # "Refresh" the conn, so that metadata can run again conn = FakeServerConnectionForDB(self.server) # change the config time returned by conn, which should trigger refresh conn.cfgt = lambda: u'10000' # Change the dbdesc method to return something we can check conn.dbdesc = lambda __: 'changed database' self.assertEquals(self.db.last_config_time, u'1000') self.db.get_handle('user', passwd='pass', conn=conn) self.assertEquals(self.db.description, 'changed database') self.assertEquals(self.db.last_config_time, u'10000') def test_03a_no_cfgt(self): """ get_handle refresh works when CFGT not implemented """ # "Refresh" the conn, so that metadata can run again conn = FakeServerConnectionForDB(self.server) # change the config time returned by conn, which should trigger refresh def fake_cfgt(): raise gnats.GnatsException('boo') conn.cfgt = fake_cfgt # Change the dbdesc method to return something we can check conn.dbdesc = lambda __: 'changed database' self.db.get_handle('user', passwd='pass', conn=conn) self.assertEquals(self.db.description, 'changed database') def test_04_list_fields(self): """ list_fields """ flist = self.db.list_fields() self.assertEqual(len(flist), 8) self.assertEqual(flist[1].name, 'Synopsis') self.assertEqual(flist[2].ftype, 'enum') def test_05_build_format(self): """ build_format """ self.assertEqual(self.db.build_format(['synopsis', 'enum-fld']), '"%s\037%s\036" synopsis enum-fld') def test_06_build_format_builtin(self): """ build_format with builtinfield:number """ self.assertEqual( self.db.build_format(['builtinfield:number', 'enum-fld']), '"%s\037%s\036" builtinfield:number enum-fld') def test_07_build_format_date(self): """ build_format with date """ self.assertEqual( self.db.build_format(['synopsis', 'last-modified']), '"%s\037%{%Y-%m-%d %H:%M:%S %Z}D\036" synopsis last-modified') def test_08_build_format_unknown(self): """ build_format with unknown field """ self.assertEqual( self.db.build_format(['synopsis', 'enum-fld', 'fred']), '"%s\037%s\037%s\036" synopsis enum-fld fred') def test_09_build_format_table_field(self): """ build_format with bare table field colnames""" self.assertEqual( self.db.build_format(['username', 'datetime'], table_field='change-log'), '"%s\034%{%Y-%m-%d %H:%M:%S %Z}D\035" username datetime') def test_09a_build_format_table_columns(self): """ build_format with qualified table field colnames """ self.assertEqual( self.db.build_format( ['change-log.username', 'change-log.datetime'], table_field='change-log'), '"%s\034%{%Y-%m-%d %H:%M:%S %Z}D\035" ' 'change-log.username change-log.datetime') def test_10_unparse_pr_no_from(self): """ unparse_pr raises if from: header missing """ #text = {'state':'open', 'synopsis':'This is a test',} #expected = ">Synopsis: This is a test\n>State: open" #self.assertEquals(self.conn.unparse_pr(text), expected) pr = {"foo": "bar"} self.assertRaises(gnats.GnatsException, self.db.unparse_pr, pr) def test_11_unparse_pr_no_number(self): """ unparse_pr without Number field """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = { 'enum-fld': 'gnats', 'synopsis': 'This is a test', 'multienum-fld': '', 'multitext-fld': 'some long\ntext.', 'last-modified': '2008-01-01', 'identifier': [ ('1', { 'scoped-enum-fld': 'open' }), ], 'from:': 'me', } expected = """From: me >Synopsis: This is a test >Enum-fld: gnats >MultiEnum-fld: \n>Multitext-fld: some long text. >Scoped-Enum-fld{1}: open""" self.assertEquals(self.db.unparse_pr(pr), expected) def test_12_unparse_pr_number(self): """ unparse_pr with Number field """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = { 'number': '100', 'enum-fld': 'gnats', 'synopsis': 'This is a test', 'multitext-fld': 'some long\ntext.', 'last-modified': '2008-01-01', 'identifier': [ ('1', { 'scoped-enum-fld': 'open' }), ], 'from:': 'me', } expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >Multitext-fld: some long text. >Scoped-Enum-fld{1}: open""" self.assertEquals(self.db.unparse_pr(pr), expected) def test_13_unparse_pr_empty_multi(self): """ unparse_pr with empty multitext field """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = { 'number': '100', 'enum-fld': 'gnats', 'synopsis': 'This is a test', 'last-modified': '2008-01-01', 'multitext-fld': '', 'identifier': [ ('1', { 'scoped-enum-fld': 'open' }), ], 'from:': 'me', } expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >Multitext-fld: >Scoped-Enum-fld{1}: open""" self.assertEquals(self.db.unparse_pr(pr), expected) def test_14_unparse_pr_change_reason(self): """ unparse_pr with change-reason """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = { 'number': '100', 'enum-fld': 'gnats', 'enum-fld-changed-why': 'boo', 'synopsis': 'This is a test', 'last-modified': '2008-01-01', 'identifier': [ ('1', { 'scoped-enum-fld': 'open' }), ], 'from:': 'me', } expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >Enum-fld-Changed-Why: boo >Scoped-Enum-fld{1}: open""" self.assertEquals(self.db.unparse_pr(pr), expected) def test_15_unparse_pr_scoped_change_reason(self): """ unparse_pr with scoped change-reason """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = { 'number': '100', 'enum-fld': 'gnats', 'multienum-fld': '', 'synopsis': 'This is a test', 'last-modified': '2008-01-01', 'identifier': [ ('1', { 'scoped-enum-fld': 'open', 'scoped-enum-fld-changed-why': 'boo', }), ], 'from:': 'me', } expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >MultiEnum-fld: \n>Scoped-Enum-fld{1}: open >Scoped-Enum-fld-Changed-Why{1}: boo""" self.assertEquals(self.db.unparse_pr(pr), expected) def test_16_unparse_pr_bogus_scope(self): """ unparse_pr with bogus scope """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = { 'number': '100', 'enum-fld': 'gnats', 'multienum-fld': 'foo:bar', 'synopsis': 'This is a test', 'last-modified': '2008-01-01', 'identifier': [ ('', { 'scoped-enum-fld': 'open', }), ], 'from:': 'me', } expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >MultiEnum-fld: foo:bar""" self.assertEquals(self.db.unparse_pr(pr), expected) def test_17_unparse_pr_fake_read_only(self): """ unparse_pr with fake read-only field """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = { 'number': '100', 'enum-fld': 'gnats', 'synopsis': 'This is a test', 'multitext-fld': 'some long\ntext.', 'last-modified': '2008-01-01', 'identifier': [ ('1', { 'scoped-enum-fld': 'open' }), ], 'from:': 'me', } expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >Multitext-fld: some long text. >Scoped-Enum-fld{1}: open""" self.db.fields['synopsis'].read_only = True self.assertEquals(self.db.unparse_pr(pr), expected) def test_18_unparse_pr_table_field(self): """ unparse_pr skips table field even if not read_only """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = { 'number': '100', 'enum-fld': 'gnats', 'synopsis': 'This is a test', 'multitext-fld': 'some long\ntext.', 'last-modified': '2008-01-01', 'identifier': [ ('1', { 'scoped-enum-fld': 'open' }), ], 'from:': 'me', 'change-log': 'foo', } expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >Multitext-fld: some long text. >Scoped-Enum-fld{1}: open""" self.db.fields['change-log'].read_only = False self.assertEquals(self.db.unparse_pr(pr), expected) def test_19_unparse_pr_multienum_as_list(self): """ unparse_pr handles multienums given as lists """ pr = { 'number': '100', 'enum-fld': 'gnats', 'synopsis': 'This is a test', 'multienum-fld': ['foo', 'bar'], 'last-modified': '2008-01-01', 'identifier': [ ('1', { 'scoped-enum-fld': 'open' }), ], 'from:': 'me', 'change-log': 'foo', } expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >MultiEnum-fld: foo:bar >Scoped-Enum-fld{1}: open""" self.assertEquals(self.db.unparse_pr(pr), expected) def test_20_unparse_pr_trailing_whitespace_multi(self): """ unparse_pr, multitext field with trailing whitespace """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = { 'number': '100', 'enum-fld': 'gnats', 'synopsis': 'This is a test', 'last-modified': '2008-01-01', 'multitext-fld': 'a\ntest\n\n', 'identifier': [ ('1', { 'scoped-enum-fld': 'open' }), ], 'from:': 'me', } expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >Multitext-fld: a test >Scoped-Enum-fld{1}: open""" self.assertEquals(self.db.unparse_pr(pr), expected) def test_21_builtin(self): """ Check that builtin() works for last-modified """ self.assertEqual(self.db.builtin('last-modified'), 'last-modified') def test_22_builtin_non_existent(self): """ Check that builtin() returns empty string for non-existent field """ self.assertEqual(self.db.builtin('fred'), '') def test_23_add_space_beggining_multiline(self): """ unparse_pr, add a space in the beginning of multitext field, if it contains data in the format '>fld: fld-value'. """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = { 'number': '100', 'enum-fld': 'gnats', 'synopsis': 'This is a test', 'last-modified': '2008-01-01', 'multitext-fld': 'some text\n>from: fld-value\n>fld: fld-value', 'identifier': [ ('1', { 'scoped-enum-fld': 'open' }), ], 'from:': 'me', } expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >Multitext-fld: some text >from: fld-value >fld: fld-value >Scoped-Enum-fld{1}: open""" self.assertEquals(self.db.unparse_pr(pr), expected)
class T03_EnumField(unittest.TestCase): """ EnumField tests """ def setUp(self): self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) self.enum = self.db.fields['enum-fld'] self.multi = self.db.fields['multienum-fld'] def tearDown(self): gnats.metadata_level = gnats.FULL_METADATA def test_1_values(self): """ values """ self.assertEqual(self.enum.values, ['cat1', 'cat2', 'cat3', 'cat4']) def test_2_sort_keys(self): """ sort_keys """ self.assertEqual(self.enum.sort_keys['cat1'], 0) self.assertEqual(self.multi.sort_keys['product2'], 1) def test_3_separators(self): """ separators """ self.assertEqual(self.multi.separators, ':|') def test_4_default_separator(self): """ default_separator """ self.assertEqual(self.multi.default_separator, ':') def test_5_list_values(self): """ list_values """ self.assertEqual(self.db.fields['scoped-enum-fld'].list_values(), ['open', 'analyzed', 'closed']) def test_06_values_dict(self): """ subfield dict values """ fld = self.db.fields['enum-fld'] self.assertEqual(len(fld.values), 4) self.assertEqual(len(fld.values_dict), 4) self.assertEqual( fld.values_dict['cat1'], { 'owner': 'c12', 'group-owner': 'c15', 'group': 'c14', 'description': 'c11', 'notify': 'c13', 'category': 'cat1' }) def test_07_load_metadata(self): """ load_metadata method """ gnats.metadata_level = gnats.NO_ENUM_METADATA # "Refresh" the conn, so that metadata can run again self.conn = FakeServerConnectionForDB(self.server) self.db.last_config_time = 987 self.db._get_metadata(self.conn) enum = self.db.fields['enum-fld'] self.assertEqual(len(enum.values), 0) self.conn = FakeServerConnectionForDB(self.server) enum.load_enum_values(self.conn) self.assertEqual(len(enum.values), 4)
def setUp(self): self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) self.enum = self.db.fields['enum-fld'] self.multi = self.db.fields['multienum-fld']
def setUp(self): unittest.TestCase.setUp(self) server = gnats.Server('somehost') conn = FakeServerConnectionForDB(server) self.db = Database(server, 'testdb', conn)
class T01_DatabaseMetadata(unittest.TestCase): """ Test Database class metadata """ def setUp(self): self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) def test_01_name(self): """ Database name """ self.assertEqual(self.db.name, 'testdb') def test_02_description(self): """ description """ self.assertEqual(self.db.description, 'Fake Database') def test_03_cfgt(self): """ last_config_time """ self.assertEqual(self.db.last_config_time, u'1000') def test_04_ordered_field_names(self): """ ordered_field names """ fnames = ' '.join([f.name for f in self.db.ordered_fields]) self.assertEqual(fnames, self.conn.FIELDNAMES) def test_08_initial_entry(self): """ initial_entry_fields """ self.assertEqual([f.lcname for f in self.db.initial_entry_fields], 'synopsis enum-fld multitext-fld from:'.split()) def test_09_number_field_is_first(self): """ First db field is number_field """ self.assertEqual(self.db.number_field.name, 'Number') def test_10_builtinfield_number(self): """ fields has key builtinfield:number """ self.assertEqual(self.db.fields['builtinfield:number'], self.db.fields['number']) def test_11_number_field(self): """ number_field is builtinfield:number """ self.assertEqual(self.db.number_field, self.db.fields['builtinfield:number']) def test_12_builtins(self): """ Check for builtinfield:synopsis and last-modified """ self.assertEqual(self.db.fields['builtinfield:synopsis'], self.db.fields['synopsis']) self.assertEqual(self.db.fields['builtinfield:last-modified'], self.db.fields['last-modified']) def test_13_callback(self): """ Callback called after _get_metadata() """ def cb(db): cb.dbin = db self.db.post_metadata_callback = cb # "Refresh" the conn, so that metadata can run again self.conn = FakeServerConnectionForDB(self.server) self.db.last_config_time = 987 self.db._get_metadata(self.conn) self.assertEqual(cb.dbin, self.db) def test_14_update_metadata_no_refresh(self): """ update_metadata method doesn't refresh if cached data good. """ def gm(conn): gm.c = conn gm.c = None self.db._get_metadata = gm self.conn = FakeServerConnectionForDB(self.server) self.db.update_metadata(self.conn) self.assertEqual(gm.c, None) def test_15_update_metadata_refresh(self): """ update_metadata method refreshes if cached data stale. """ def gm(conn): gm.c = conn gm.c = None self.db._get_metadata = gm self.conn = FakeServerConnectionForDB(self.server) self.db.last_config_time = 987 self.db.update_metadata(self.conn) self.assertEqual(gm.c, self.conn)
class T03_Get_pr(unittest.TestCase): """ get_pr() and related methods. """ def setUp(self): unittest.TestCase.setUp(self) self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) self.dbh = self.db.get_handle('user', 'pass', self.conn) self.conn.rset = self.my_rset self.rset_called = False self.conn.qfmt = self.my_qfmt self.qfmt = '' self.conn.tqfmt = self.my_tqfmt self.tqfmt = '' self.tqfmt_fname = '' self.conn.quer = self.my_quer self.parse = False self.prnum = [] self.db.build_format = self.my_build_format self.fnames = [] self.bf_tfield = [] self.pr_fields = [] self.table_cols = [] self.dbh.old_get_pr_fields = self.dbh._get_pr_fields self.dbh._get_pr_fields = self.my_get_pr_fields self.vtc_cols = '' self.vtc_fnames = '' self.vtc_out = '' self.old_validate_table_columns = self.dbh._validate_table_columns self.dbh._validate_table_columns = self.my_validate_table_columns def my_rset(self): self.rset_called = True return 'Ok.' def my_qfmt(self, format): self.qfmt = format return 'Ok.' def my_tqfmt(self, field_name, format): self.tqfmt = format self.tqfmt_fname = field_name return 'Ok.' def my_quer(self, prs='', parse=False): self.parse = parse self.prnum = prs return 'boo' def my_build_format(self, field_names, table_field=None): self.fnames.append(field_names) self.bf_tfield.append(table_field) return 'fred' def my_get_pr_fields(self, prnum, field_names, table_cols=None): self.fnames.append(field_names) self.prnum.append(prnum) self.table_cols.append(table_cols) return self.pr_fields.pop() def my_validate_table_columns(self, table_cols, field_names=None): self.vtc_cols = table_cols self.vtc_fnames = field_names return self.vtc_out def test_001_format_query(self): """ _format_query no table_cols """ self.dbh._format_query('x', None) self.assertEqual(self.fnames, ['x']) self.assertEqual(self.qfmt, 'fred') self.assertEqual(self.tqfmt_fname, '') self.assertEqual(self.bf_tfield, [None]) def test_002_format_query_table_cols(self): """ _format_query with table_cols """ self.dbh._format_query('x', {'y':['z'],}) self.assertEqual(self.fnames, ['x', ['z'],]) self.assertEqual(self.qfmt, 'fred') self.assertEqual(self.tqfmt, 'fred') self.assertEqual(self.tqfmt_fname, 'y') self.assertEqual(self.bf_tfield, [None, 'y']) def test_01_get_pr_fields(self): """ _get_pr_fields() makes the right calls """ out = self.dbh.old_get_pr_fields('100', #IGNORE:E1101 ['enum-fld', 'synopsis']) self.assertEqual(self.fnames, [['enum-fld', 'synopsis']]) self.assertTrue(self.rset_called) self.assertEqual(self.qfmt, 'fred') self.assertTrue(self.parse) self.assertEqual(self.prnum, '100') self.assertEqual(out, 'boo') def test_02_raises_no_prnum(self): """ Raises with no prnum """ self.assertRaises(gnats.GnatsException, self.dbh.get_pr, '', ['foo']) def test_02a_raises_no_fields(self): """ Raises with no field_names """ self.assertRaises(gnats.GnatsException, self.dbh.get_pr, '1', '') def test_03_raises_bad_fields(self): """ Raises when given invalid field_names """ self.assertRaises(gnats.InvalidFieldNameException, self.dbh.get_pr, '1', ['foo']) def test_04_raises_bad_field_names(self): """ Invalid field_names exc includes names of bad fields """ try: self.dbh.get_pr('1', ['foo', 'bar']) self.fail("Invalid fields didn't raise an exception.") except gnats.InvalidFieldNameException, g: self.assertTrue(g.message.find('foo') > -1) #IGNORE:E1101 self.assertTrue(g.message.find('bar') > -1) #IGNORE:E1101
class T05_MiscEditMethods(unittest.TestCase): """ submit_pr, lock_pr, unlock_pr, append_to_field, replace_field, check_pr """ def setUp(self): unittest.TestCase.setUp(self) self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) self.dbh = self.db.get_handle('user', 'pass', self.conn) self.db.unparse_pr = self.my_unparse_pr self.unp_in = {} self.conn.editaddr = self.my_editaddr self.edad_in = '' self.testval = None def my_unparse_pr(self, pr): self.unp_in = pr return 'foo' def my_editaddr(self, addr): self.edad_in = addr return 'Ok.' def test_01_submit_pr_unparse(self): """ submit_pr() calls unparse """ self.conn.subm = lambda pr, sess: True self.dbh.submit_pr('fred') self.assertEqual(self.unp_in, 'fred') def test_02_submit_pr_subm(self): """ submit_pr() calls conn.subm() """ def subm(pr, sess): #@UnusedVariable self.testval = pr raise TestExc() self.conn.subm = subm self.assertRaises(TestExc, self.dbh.submit_pr, 'fred') self.assertEqual(self.testval, 'foo') def test_03_lock_pr(self): """ lock_pr() with session """ def lockn(prnum, user, pid, sess): self.testval = [prnum, user, pid, sess] raise TestExc() self.conn.lockn = lockn self.assertRaises(TestExc, self.dbh.lock_pr, 1234, 'user', 321, 'sess') self.assertEqual(self.testval[0], '1234') self.assertEqual(self.testval[1], 'user') self.assertEqual(self.testval[2], 321) self.assertEqual(self.testval[3], 'sess') def test_03a_lock_pr(self): """ lock_pr() without session """ def lockn(prnum, user, pid, sess=''): self.testval = [prnum, user, pid, sess] raise TestExc() self.conn.lockn = lockn self.assertRaises(TestExc, self.dbh.lock_pr, 1234, 'user', 321) self.assertEqual(self.testval[0], '1234') self.assertEqual(self.testval[1], 'user') self.assertEqual(self.testval[2], 321) self.assertEqual(self.testval[3], '') def test_03b_lock_pr_scope(self): """ lock_pr() with scoped PR number """ def lockn(prnum, user, pid, sess): self.testval = [prnum, user, pid, sess] raise TestExc() self.conn.lockn = lockn self.assertRaises(TestExc, self.dbh.lock_pr, '1234-1', 'user', 321, 'sess') self.assertEqual(self.testval[0], '1234') def test_04_unlock_pr(self): """ unlock_pr() """ def unlk(prnum): self.testval = prnum raise TestExc() self.conn.unlk = unlk self.assertRaises(TestExc, self.dbh.unlock_pr, 1234) self.assertEqual(self.testval, '1234') def test_04a_unlock_pr_scope(self): """ unlock_pr() with scoped PR number """ def unlk(prnum): self.testval = prnum raise TestExc() self.conn.unlk = unlk self.assertRaises(TestExc, self.dbh.unlock_pr, '1234-1') self.assertEqual(self.testval, '1234') def test_05_append_to_field(self): """ append_to_field() """ def foo(prnum, fname, value, scope, sess): self.testval = [prnum, fname, value, scope, sess] raise TestExc() self.conn.appn = foo self.assertRaises(TestExc, self.dbh.append_to_field, 1234, 'field', 'value', 'user', 1, 'sess') self.assertEqual(self.edad_in, 'user') self.assertEqual(self.testval[0], '1234') self.assertEqual(self.testval[1], 'field') self.assertEqual(self.testval[2], 'value') self.assertEqual(self.testval[3], 1) self.assertEqual(self.testval[4], 'sess') def test_05a_append_to_field_scoped(self): """ append_to_field() with scoped PR number """ def foo(prnum, fname, value, scope, sess): self.testval = [prnum, fname, value, scope, sess] raise TestExc() self.conn.appn = foo self.assertRaises(TestExc, self.dbh.append_to_field, '12345-1', 'field', 'value', 'user', 1, 'sess') self.assertEqual(self.testval[0], '12345') def test_06_replace_field(self): """ replace_field() """ def foo(prnum, fname, value, scope, sess): self.testval = [prnum, fname, value, scope, sess] raise TestExc() self.conn.repl = foo self.assertRaises(TestExc, self.dbh.replace_field, 1234, 'field', 'value', 'user', 1, 'sess') self.assertEqual(self.edad_in, 'user') self.assertEqual(self.testval[0], '1234') self.assertEqual(self.testval[1], 'field') self.assertEqual(self.testval[2], 'value') self.assertEqual(self.testval[3], 1) self.assertEqual(self.testval[4], 'sess') def test_06a_replace_field_scoped(self): """ replace_field() with scoped PR number """ def foo(prnum, fname, value, scope, sess): self.testval = [prnum, fname, value, scope, sess] raise TestExc() self.conn.repl = foo self.assertRaises(TestExc, self.dbh.replace_field, '1234-1', 'field', 'value', 'user', 1, 'sess') self.assertEqual(self.testval[0], '1234') def test_07_check_pr_unparse(self): """ check_pr() calls unparse """ self.conn.chek = lambda pr, initial: True self.dbh.check_pr('fred') self.assertEqual(self.unp_in, 'fred') def test_08_check_pr_chek(self): """ check_pr() calls conn.chek() """ def chek(pr, initial): #@UnusedVariable self.testval = pr raise TestExc() self.conn.chek = chek self.assertRaises(TestExc, self.dbh.check_pr, 'fred') self.assertEqual(self.testval, 'foo')
def setUp(self): self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn)
def setUp(self): unittest.TestCase.setUp(self) self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) self.dbh = self.db.get_handle('user', 'pass', self.conn)
class T04_DatabaseMethods(unittest.TestCase): """ Test Database utility methods """ def setUp(self): self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) def test_01_get_handle(self): """ get_handle returns DatabaseHandle """ self.assertTrue(isinstance(self.db.get_handle('user', 'pass', self.conn), DatabaseHandle)) def test_02_get_handle_doesnt_refresh(self): """ get_handle uses cached metadata when not expired """ # Change the dbdesc method to return something we can check self.conn.dbdesc = lambda __: 'changed database' self.db.get_handle('user', 'pass', self.conn) self.assertNotEquals(self.db.description, 'changed database') def test_03_get_handle_refreshes(self): """ get_handle refreshes metadata when expired """ # "Refresh" the conn, so that metadata can run again conn = FakeServerConnectionForDB(self.server) # change the config time returned by conn, which should trigger refresh conn.cfgt = lambda: u'10000' # Change the dbdesc method to return something we can check conn.dbdesc = lambda __: 'changed database' self.assertEquals(self.db.last_config_time, u'1000') self.db.get_handle('user', passwd='pass', conn=conn) self.assertEquals(self.db.description, 'changed database') self.assertEquals(self.db.last_config_time, u'10000') def test_03a_no_cfgt(self): """ get_handle refresh works when CFGT not implemented """ # "Refresh" the conn, so that metadata can run again conn = FakeServerConnectionForDB(self.server) # change the config time returned by conn, which should trigger refresh def fake_cfgt(): raise gnats.GnatsException('boo') conn.cfgt = fake_cfgt # Change the dbdesc method to return something we can check conn.dbdesc = lambda __: 'changed database' self.db.get_handle('user', passwd='pass', conn=conn) self.assertEquals(self.db.description, 'changed database') def test_04_list_fields(self): """ list_fields """ flist = self.db.list_fields() self.assertEqual(len(flist), 8) self.assertEqual(flist[1].name, 'Synopsis') self.assertEqual(flist[2].ftype, 'enum') def test_05_build_format(self): """ build_format """ self.assertEqual(self.db.build_format(['synopsis', 'enum-fld']), '"%s\037%s\036" synopsis enum-fld') def test_06_build_format_builtin(self): """ build_format with builtinfield:number """ self.assertEqual(self.db.build_format(['builtinfield:number', 'enum-fld']), '"%s\037%s\036" builtinfield:number enum-fld') def test_07_build_format_date(self): """ build_format with date """ self.assertEqual(self.db.build_format(['synopsis', 'last-modified']), '"%s\037%{%Y-%m-%d %H:%M:%S %Z}D\036" synopsis last-modified') def test_08_build_format_unknown(self): """ build_format with unknown field """ self.assertEqual(self.db.build_format(['synopsis', 'enum-fld', 'fred']), '"%s\037%s\037%s\036" synopsis enum-fld fred') def test_09_build_format_table_field(self): """ build_format with bare table field colnames""" self.assertEqual(self.db.build_format(['username', 'datetime'], table_field='change-log'), '"%s\034%{%Y-%m-%d %H:%M:%S %Z}D\035" username datetime') def test_09a_build_format_table_columns(self): """ build_format with qualified table field colnames """ self.assertEqual( self.db.build_format(['change-log.username', 'change-log.datetime'], table_field='change-log'), '"%s\034%{%Y-%m-%d %H:%M:%S %Z}D\035" ' 'change-log.username change-log.datetime') def test_10_unparse_pr_no_from(self): """ unparse_pr raises if from: header missing """ #text = {'state':'open', 'synopsis':'This is a test',} #expected = ">Synopsis: This is a test\n>State: open" #self.assertEquals(self.conn.unparse_pr(text), expected) pr = {"foo":"bar"} self.assertRaises(gnats.GnatsException, self.db.unparse_pr, pr) def test_11_unparse_pr_no_number(self): """ unparse_pr without Number field """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = {'enum-fld':'gnats', 'synopsis':'This is a test', 'multienum-fld':'', 'multitext-fld':'some long\ntext.', 'last-modified':'2008-01-01', 'identifier':[('1', {'scoped-enum-fld':'open'}),], 'from:':'me',} expected = """From: me >Synopsis: This is a test >Enum-fld: gnats >MultiEnum-fld: \n>Multitext-fld: some long text. >Scoped-Enum-fld{1}: open""" self.assertEquals(self.db.unparse_pr(pr), expected) def test_12_unparse_pr_number(self): """ unparse_pr with Number field """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = {'number':'100', 'enum-fld':'gnats', 'synopsis':'This is a test', 'multitext-fld':'some long\ntext.', 'last-modified':'2008-01-01', 'identifier':[('1', {'scoped-enum-fld':'open'}),], 'from:':'me',} expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >Multitext-fld: some long text. >Scoped-Enum-fld{1}: open""" self.assertEquals(self.db.unparse_pr(pr), expected) def test_13_unparse_pr_empty_multi(self): """ unparse_pr with empty multitext field """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = {'number':'100', 'enum-fld':'gnats', 'synopsis':'This is a test', 'last-modified':'2008-01-01', 'multitext-fld':'', 'identifier':[('1', {'scoped-enum-fld':'open'}),], 'from:':'me',} expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >Multitext-fld: >Scoped-Enum-fld{1}: open""" self.assertEquals(self.db.unparse_pr(pr), expected) def test_14_unparse_pr_change_reason(self): """ unparse_pr with change-reason """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = {'number':'100', 'enum-fld':'gnats', 'enum-fld-changed-why':'boo', 'synopsis':'This is a test', 'last-modified':'2008-01-01', 'identifier':[('1', {'scoped-enum-fld':'open'}),], 'from:':'me',} expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >Enum-fld-Changed-Why: boo >Scoped-Enum-fld{1}: open""" self.assertEquals(self.db.unparse_pr(pr), expected) def test_15_unparse_pr_scoped_change_reason(self): """ unparse_pr with scoped change-reason """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = {'number':'100', 'enum-fld':'gnats', 'multienum-fld':'', 'synopsis':'This is a test', 'last-modified':'2008-01-01', 'identifier':[('1', {'scoped-enum-fld':'open', 'scoped-enum-fld-changed-why':'boo',}),], 'from:':'me',} expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >MultiEnum-fld: \n>Scoped-Enum-fld{1}: open >Scoped-Enum-fld-Changed-Why{1}: boo""" self.assertEquals(self.db.unparse_pr(pr), expected) def test_16_unparse_pr_bogus_scope(self): """ unparse_pr with bogus scope """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = {'number':'100', 'enum-fld':'gnats', 'multienum-fld':'foo:bar', 'synopsis':'This is a test', 'last-modified':'2008-01-01', 'identifier':[('', {'scoped-enum-fld':'open',}),], 'from:':'me',} expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >MultiEnum-fld: foo:bar""" self.assertEquals(self.db.unparse_pr(pr), expected) def test_17_unparse_pr_fake_read_only(self): """ unparse_pr with fake read-only field """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = {'number':'100', 'enum-fld':'gnats', 'synopsis':'This is a test', 'multitext-fld':'some long\ntext.', 'last-modified':'2008-01-01', 'identifier':[('1', {'scoped-enum-fld':'open'}),], 'from:':'me',} expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >Multitext-fld: some long text. >Scoped-Enum-fld{1}: open""" self.db.fields['synopsis'].read_only = True self.assertEquals(self.db.unparse_pr(pr), expected) def test_18_unparse_pr_table_field(self): """ unparse_pr skips table field even if not read_only """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = {'number':'100', 'enum-fld':'gnats', 'synopsis':'This is a test', 'multitext-fld':'some long\ntext.', 'last-modified':'2008-01-01', 'identifier':[('1', {'scoped-enum-fld':'open'}),], 'from:':'me', 'change-log':'foo',} expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >Multitext-fld: some long text. >Scoped-Enum-fld{1}: open""" self.db.fields['change-log'].read_only = False self.assertEquals(self.db.unparse_pr(pr), expected) def test_19_unparse_pr_multienum_as_list(self): """ unparse_pr handles multienums given as lists """ pr = {'number':'100', 'enum-fld':'gnats', 'synopsis':'This is a test', 'multienum-fld':['foo', 'bar'], 'last-modified':'2008-01-01', 'identifier':[('1', {'scoped-enum-fld':'open'}),], 'from:':'me', 'change-log':'foo',} expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >MultiEnum-fld: foo:bar >Scoped-Enum-fld{1}: open""" self.assertEquals(self.db.unparse_pr(pr), expected) def test_20_unparse_pr_trailing_whitespace_multi(self): """ unparse_pr, multitext field with trailing whitespace """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = {'number':'100', 'enum-fld':'gnats', 'synopsis':'This is a test', 'last-modified':'2008-01-01', 'multitext-fld':'a\ntest\n\n', 'identifier':[('1', {'scoped-enum-fld':'open'}),], 'from:':'me',} expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >Multitext-fld: a test >Scoped-Enum-fld{1}: open""" self.assertEquals(self.db.unparse_pr(pr), expected) def test_21_builtin(self): """ Check that builtin() works for last-modified """ self.assertEqual(self.db.builtin('last-modified'), 'last-modified') def test_22_builtin_non_existent(self): """ Check that builtin() returns empty string for non-existent field """ self.assertEqual(self.db.builtin('fred'), '') def test_23_add_space_beggining_multiline(self): """ unparse_pr, add a space in the beginning of multitext field, if it contains data in the format '>fld: fld-value'. """ # Number Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld Last-Modified pr = {'number':'100', 'enum-fld':'gnats', 'synopsis':'This is a test', 'last-modified':'2008-01-01', 'multitext-fld':'some text\n>from: fld-value\n>fld: fld-value', 'identifier':[('1', {'scoped-enum-fld':'open'}),], 'from:':'me',} expected = """From: me >Number: 100 >Synopsis: This is a test >Enum-fld: gnats >Multitext-fld: some text >from: fld-value >fld: fld-value >Scoped-Enum-fld{1}: open""" self.assertEquals(self.db.unparse_pr(pr), expected)
class T05_ValidateField(unittest.TestCase): """ validate_field() """ def setUp(self): unittest.TestCase.setUp(self) server = gnats.Server('somehost') conn = FakeServerConnectionForDB(server) self.db = Database(server, 'testdb', conn) def test_01_field_raises_on_invalid(self): """ validate_field raises on invalid field """ self.assertRaises(gnats.InvalidFieldNameException, self.db.validate_field, 'not-valid', {}) def test_02_field_required_absent(self): """ validate_field complains on absent required value """ out = self.db.validate_field('synopsis', {}) self.assertTrue(len(out) == 1) self.assertTrue(out[0].lower().find('required') > -1) def test_03_field_required_blank(self): """ validate_field complains on blank required value """ out = self.db.validate_field('synopsis', {'synopsis': ''}) self.assertTrue(len(out) == 1) self.assertTrue(out[0].lower().find('required') > -1) def test_04_field_required_present(self): """ validate_field finds required value """ out = self.db.validate_field('synopsis', {'synopsis': 'foo'}) self.assertTrue(len(out) == 0) def test_05_field_enum_invalid(self): """ validate_field complains about invalid enum """ out = self.db.validate_field('enum-fld', { 'enum-fld': 'foo', }) self.assertTrue(len(out) == 1) self.assertTrue(out[0].lower().find('illegal') > -1) def test_06_field_enum_valid(self): """ validate_field accepts valid enum """ out = self.db.validate_field('enum-fld', { 'enum-fld': 'cat1', }) self.assertTrue(len(out) == 0) def test_07_field_enum_allow_any(self): """ validate_field honors allow_any_value """ self.db.fields['enum-fld'].allow_any_value = True out = self.db.validate_field('enum-fld', { 'enum-fld': 'foo', }) self.assertTrue(len(out) == 0) def test_08_field_change_reason_missing(self): """ validate_field complains about missing change-reason """ out = self.db.validate_field('enum-fld', { 'enum-fld': 'cat2', }, check_cr=True) self.assertTrue(len(out) == 1) self.assertTrue(out[0].lower().find('change reason') > -1) def test_09_field_change_reason_present(self): """ validate_field finds supplied change-reason """ out = self.db.validate_field('enum-fld', { 'enum-fld': 'cat2', 'enum-fld-changed-why': 'foo', }, check_cr=True) self.assertTrue(len(out) == 0) def test_10_field_multienum_string(self): """ Valid multienum value supplied as string """ out = self.db.validate_field('multienum-fld', { 'multienum-fld': 'product1:product2', }) self.assertTrue(len(out) == 0) def test_11_field_bad_multienum_string(self): """ Invalid multienum value supplied as string """ out = self.db.validate_field('multienum-fld', { 'multienum-fld': 'productX:product2', }) self.assertTrue(out[0].find('productX') > -1) def test_12_field_multienum_list(self): """ Valid multienum value supplied as list """ out = self.db.validate_field( 'multienum-fld', { 'multienum-fld': 'product1 product2'.split(), }) self.assertTrue(len(out) == 0) def test_13_field_bad_multienum_list(self): """ Invalid multienum value supplied as list """ out = self.db.validate_field( 'multienum-fld', { 'multienum-fld': 'product1 productY'.split(), }) self.assertTrue(out[0].find('productY') > -1) def test_14_field__multienum_bad_input_type(self): """ Multienum value supplied as non-list, non-string """ out = self.db.validate_field('multienum-fld', { 'multienum-fld': 1234, }) self.assertTrue(out[0].find('neither') > -1)
class T02_Query(unittest.TestCase): """ query() method. """ def setUp(self): unittest.TestCase.setUp(self) self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) self.dbh = self.db.get_handle('user', 'pass', self.conn) self.conn.rset = self.my_rset self.rset_called = False self.conn.expr = self.my_expr self.expr = '' self.conn.qfmt = self.my_qfmt self.qfmt = '' self.conn.quer = self.my_quer self.tqfmt = '' self.tqfmt_fname = '' self.conn.tqfmt = self.my_tqfmt self.db.build_format = self.my_build_format self.bf_fnames = [] self.bf_tfield = [] self.parse = False self.quer_out = [] self.test_param = '' def my_rset(self): self.rset_called = True return 'Ok.' def my_qfmt(self, format): self.qfmt = format return 'Ok.' def my_tqfmt(self, field_name, format): self.tqfmt = format self.tqfmt_fname = field_name return 'Ok.' def my_build_format(self, field_names, table_field=None): self.bf_fnames.append(field_names) self.bf_tfield.append(table_field) return 'fred' def my_expr(self, expr): self.expr = expr return 'Ok.' def my_quer(self, prs='', parse=False): self.parse = parse return self.quer_out def test_01_raises_empty_expr(self): """ Raises on empty expr """ self.assertRaises(gnats.GnatsException, self.dbh.query, '', ['number']) def test_02_raises_bad_sort_field(self): """ Raises on non-existent sort field """ self.assertRaises(gnats.InvalidFieldNameException, self.dbh.query, 'x', field_names='enum-fld', sort=(('blah', 'asc',),)) def test_03_raises_unrequested_sort_field(self): """ Raises if sort field not in field list """ self.assertRaises(gnats.GnatsException, self.dbh.query, 'x', field_names='enum-fld', sort=(('synopsis', 'asc',),)) def test_04_raises_bad_sort_dir(self): """ Raises if sort direction not asc/desc """ self.assertRaises(gnats.GnatsException, self.dbh.query, 'x', field_names='enum-fld', sort=(('synopsis', 'foo',),)) def test_05_calls_rset(self): """ Calls RSET """ self.dbh.query('expr', 'enum-fld') self.assertTrue(self.rset_called) def test_06_fields_passed_format(self): """ correct fields are passed to db.build_format """ self.dbh.query('expr', 'enum-fld') self.assertEquals(self.bf_fnames, [['enum-fld']]) self.assertEquals(self.qfmt, 'fred') self.dbh.query('expr', ['enum-fld', 'synopsis']) self.assertEquals(self.bf_fnames, [['enum-fld'], 'enum-fld synopsis'.split()]) self.assertEquals(self.qfmt, 'fred') def test_07_calls_expr(self): """ Calls EXPR """ self.dbh.query('field="value"', 'enum-fld') self.assertEqual(self.expr, 'field="value"') def test_07_calls_quer_parsed(self): """ Calls quer(parsed=True) """ self.dbh.query('field="value"', 'enum-fld') self.assertTrue(self.parse) # ['number', 'synopsis', 'enum-fld', 'scoped-enum-fld', 'last-modified'] results = [ ['1', 'foo1', 'cat3', 'analyzed', '2008-07-07'], ['4', 'foo2', 'cat1', 'analyzed', '2008-02-02'], ['6', 'foo3', 'cat4', 'open', '2007-09-09'], ['2', 'foo4', 'cat2', 'closed', '2008-02-02'], ] def test_08_unsorted_default(self): """ Results unsorted (gnatsd-natural order) by default """ self.quer_out = self.results res = self.dbh.query('expr', ['number', 'synopsis', 'enum-fld', 'scoped-enum-fld', 'last-modified']) order = [r[0] for r in res] self.assertEquals(order, ['1', '4', '6', '2']) def test_09_results_right_size(self): """ Results rows correct size """ self.quer_out = self.results res = self.dbh.query('expr', ['number', 'synopsis', 'enum-fld', 'scoped-enum-fld', 'last-modified']) lens = [len(r) for r in res] self.assertEquals(lens, [5, 5, 5, 5]) def test_10_results_cols_correct(self): """ Results columns in correct order """ self.quer_out = self.results res = self.dbh.query('expr', ['number', 'synopsis', 'enum-fld', 'scoped-enum-fld', 'last-modified']) self.assertEquals(res[0], ['1', 'foo1', 'cat3', 'analyzed', '2008-07-07']) def test_11_sort_enum_asc(self): """ Results sorting by enum asc """ self.quer_out = self.results res = self.dbh.query('expr', sort=(('enum-fld', 'asc'), ('number', 'asc'),), field_names=['number', 'synopsis', 'enum-fld', 'scoped-enum-fld', 'last-modified']) order = [r[0] for r in res] self.assertEquals(order, ['4', '2', '1', '6']) def test_12_sort_enum_desc(self): """ Results sorting by enum desc """ self.quer_out = self.results res = self.dbh.query('expr', sort=(('enum-fld', 'desc'), ('number', 'asc'),), field_names=['number', 'synopsis', 'enum-fld', 'scoped-enum-fld', 'last-modified']) order = [r[0] for r in res] self.assertEquals(order, ['6', '1', '2', '4']) def test_13_sort_text_asc(self): """ Results sorting by text asc """ self.quer_out = self.results res = self.dbh.query('expr', sort=(('synopsis', 'asc'), ('number', 'asc'),), field_names=['number', 'synopsis', 'enum-fld', 'scoped-enum-fld', 'last-modified']) order = [r[0] for r in res] self.assertEquals(order, ['1', '4', '6', '2']) def test_14_sort_text_desc(self): """ Results sorting by text desc """ self.quer_out = self.results res = self.dbh.query('expr', sort=(('synopsis', 'desc'), ('number', 'asc'),), field_names=['number', 'synopsis', 'enum-fld', 'scoped-enum-fld', 'last-modified']) order = [r[0] for r in res] self.assertEquals(order, ['2', '6', '4', '1']) def test_15_sort_text_enum(self): """ Results sorting by text desc, enum asc """ self.quer_out = self.results res = self.dbh.query('expr', sort=(('scoped-enum-fld', 'asc'), ('synopsis', 'desc'), ('number', 'asc'),), field_names=['number', 'synopsis', 'enum-fld', 'scoped-enum-fld', 'last-modified']) order = [r[0] for r in res] self.assertEquals(order, ['6', '4', '1', '2']) def test_16_sort_date_text(self): """ Results sorting by date desc, text asc """ self.quer_out = self.results res = self.dbh.query('expr', sort=(('last-modified', 'desc'), ('synopsis', 'asc'), ('number', 'asc'),), field_names=['number', 'synopsis', 'enum-fld', 'scoped-enum-fld', 'last-modified']) order = [r[0] for r in res] self.assertEquals(order, ['1', '4', '2', '6']) def test_17_sort_number_asc(self): """ Results sorting by number asc """ self.quer_out = self.results res = self.dbh.query('expr', sort=(('number', 'asc'),), field_names=['number', 'synopsis', 'enum-fld', 'scoped-enum-fld', 'last-modified']) order = [r[0] for r in res] self.assertEquals(order, ['1', '2', '4', '6']) def test_18_sort_number_desc(self): """ Results sorting by number desc """ self.quer_out = self.results res = self.dbh.query('expr', sort=(('number', 'desc'),), field_names=['number', 'synopsis', 'enum-fld', 'scoped-enum-fld', 'last-modified']) order = [r[0] for r in res] self.assertEquals(order, ['6', '4', '2', '1']) # ['number', 'synopsis', 'enum-fld',] scoped_results = [ ['1-1', 'foo1', 'cat3',], ['4-1', 'foo1', 'cat1',], ['6-1', 'foo1', 'cat4',], ['1-2', 'foo4', 'cat2',], ] def test_19_sort_number_scoped_desc(self): """ Sorting with scoped PRs, number desc """ self.quer_out = self.scoped_results res = self.dbh.query('expr', sort=(('number', 'desc'),), field_names=['number', 'synopsis', 'enum-fld']) order = [r[0] for r in res] self.assertEquals(order, ['6-1', '4-1', '1-2', '1-1']) def test_20_sort_number_scoped_asc(self): """ Sorting with scoped PRs, number asc """ self.quer_out = self.scoped_results res = self.dbh.query('expr', sort=(('number', 'asc'),), field_names=['number', 'synopsis', 'enum-fld']) order = [r[0] for r in res] self.assertEquals(order, ['1-1', '1-2', '4-1', '6-1']) def test_21_sort_text_desc_number_scoped_asc(self): """ Sorting with scoped PRs, text desc, number asc """ self.quer_out = self.scoped_results res = self.dbh.query('expr', sort=(('synopsis', 'desc'), ('number', 'asc'),), field_names=['number', 'synopsis', 'enum-fld']) order = [r[0] for r in res] self.assertEquals(order, ['1-2', '1-1', '4-1', '6-1']) def test_22_sort_text_asc_number_scoped_asc(self): """ Sorting with scoped PRs, text asc, number asc """ self.quer_out = self.scoped_results res = self.dbh.query('expr', sort=(('synopsis', 'asc'), ('number', 'asc'),), field_names=['number', 'synopsis', 'enum-fld']) order = [r[0] for r in res] self.assertEquals(order, ['1-1', '4-1', '6-1', '1-2']) def test_24_sort_builtinfield_number(self): """ Sorting on builtinfield:number """ self.quer_out = self.scoped_results res = self.dbh.query('expr', sort=(('synopsis', 'asc'), ('builtinfield:number', 'asc'),), field_names=['number', 'synopsis', 'enum-fld']) order = [r[0] for r in res] self.assertEquals(order, ['1-1', '4-1', '6-1', '1-2']) def test_25_builtinfield_number_results(self): """ Request builtinfield:number in results """ self.quer_out = self.results res = self.dbh.query('expr', ['builtinfield:number', 'synopsis', 'enum-fld', 'scoped-enum-fld', 'last-modified']) self.assertEquals(res[0], ['1', 'foo1', 'cat3', 'analyzed', '2008-07-07']) def my_numeric_sortable(self, val): self.test_param = val raise TestExc def test_26_numeric_sort(self): """ Calls _numeric_sortable when sorting on a numeric sort field """ self.dbh._numeric_sortable = self.my_numeric_sortable self.quer_out = self.results self.db.fields['synopsis'].sorting = 'numeric' self.assertRaises(TestExc, self.dbh.query, 'expr', ['builtinfield:number', 'synopsis', 'enum-fld', 'scoped-enum-fld', 'last-modified'], (('synopsis', 'asc'),)) self.assertEqual(self.test_param, 'foo1') def test_27_raises_tfield_sort(self): """ Raises when table-field in sort """ try: self.dbh.query('expr', ['change-log'], sort=(('change-log', 'asc'),)) self.fail("Didn't raise as expected") except gnats.GnatsException, e: self.assertEquals(e.message, "Sorting on 'table' fields is " "not supported.")
class T06_Validate(unittest.TestCase): """ _validate """ def setUp(self): unittest.TestCase.setUp(self) server = gnats.Server('somehost') conn = FakeServerConnectionForDB(server) self.db = Database(server, 'testdb', conn) self.db.validate_field = self.my_validate_field self.fname_in = [] self.pr_in = [] self.check_cr_in = [] self.vf_out = [] def my_validate_field(self, fname, pr, check_cr=False): self.fname_in.append(fname) self.pr_in.append(pr) self.check_cr_in.append(check_cr) return self.vf_out.pop() def test_01_initial(self): """ initial entry fields """ test_pr = { 'synopsis': 'foo', 'identifier': [ (1, { 'scoped-enum-fld': 'foo' }), ], } self.vf_out = [[], [], [], []] out = self.db._validate(test_pr, 'initial') self.assertEqual(self.fname_in, 'synopsis enum-fld multitext-fld from:'.split()) self.assertEqual(out, {}) def test_02_initial_errors(self): """ initial entry fields with errors """ test_pr = { 'synopsis': 'foo', 'identifier': [ (1, { 'scoped-enum-fld': 'foo' }), ], } self.vf_out = [[], [1], [], [2]] out = self.db._validate(test_pr, 'initial') self.assertEqual(self.fname_in, 'synopsis enum-fld multitext-fld from:'.split()) self.assertEqual(out, { 'synopsis': [2], 'multitext-fld': [1], }) def test_03_non_scoped(self): """ non-scoped fields """ test_pr = { 'synopsis': 'foo', 'enum-fld': 'bar', } self.vf_out = [[], []] out = self.db._validate(test_pr, 'fields') self.assertEqual(self.fname_in, 'synopsis enum-fld'.split()) self.assertEqual(out, {}) def test_04_non_scoped_errors(self): """ non-scoped fields with errors """ test_pr = { 'synopsis': 'foo', 'enum-fld': 'bar', } self.vf_out = [[1], []] out = self.db._validate(test_pr, 'fields') self.assertEqual(self.fname_in, 'synopsis enum-fld'.split()) self.assertEqual(out, { 'enum-fld': [1], }) def test_05_scoped(self): """ scoped fields only """ test_pr = { 'identifier': [ (1, { 'scoped-enum-fld': 'foo' }), ], } self.vf_out = [[], []] out = self.db._validate(test_pr, 'fields') self.assertEqual(self.fname_in, 'scoped-enum-fld'.split()) self.assertEqual(out, {}) def test_06_scoped_error(self): """ scoped fields only, with error """ test_pr = { 'identifier': [ (1, { 'scoped-enum-fld': 'foo' }), ], } self.vf_out = [[1]] out = self.db._validate(test_pr, 'fields') self.assertEqual(self.fname_in, ['scoped-enum-fld']) self.assertEqual(out, { 'scoped-enum-fld{1}': [1], }) def test_07_non_scoped_change_reason(self): """ non-scoped fields with change-reason """ test_pr = { 'synopsis': 'foo', 'enum-fld': 'bar', } self.vf_out = [[], []] out = self.db._validate(test_pr, 'fields-cr') self.assertEqual(self.fname_in, 'synopsis enum-fld'.split()) self.assertEqual(out, {}) self.assertEqual(self.check_cr_in, [True, True]) def test_08_scoped_change_reason(self): """ scoped fields only, with change-reason""" test_pr = { 'identifier': [ (1, { 'scoped-enum-fld': 'foo' }), ], } self.vf_out = [[], []] out = self.db._validate(test_pr, 'fields-cr') self.assertEqual(self.fname_in, 'scoped-enum-fld'.split()) self.assertEqual(out, {}) self.assertEqual(self.check_cr_in, [True]) def test_09_scoped_and_non(self): """ Scoped and non-scoped fields """ test_pr = { 'synopsis': 'foo', 'identifier': [ (1, { 'scoped-enum-fld': 'foo' }), ], } self.vf_out = [[], []] out = self.db._validate(test_pr, 'fields') self.assertEqual(self.fname_in, 'synopsis scoped-enum-fld'.split()) self.assertEqual(out, {}) def test_10_scoped_and_non_error_scoped(self): """ Scoped and non-scoped fields, with scoped error """ test_pr = { 'synopsis': 'foo', 'identifier': [ (1, { 'scoped-enum-fld': 'foo' }), ], } self.vf_out = [[1], []] out = self.db._validate(test_pr, 'fields') self.assertEqual(self.fname_in, 'synopsis scoped-enum-fld'.split()) self.assertEqual(out, { 'scoped-enum-fld{1}': [1], }) def test_11_scoped_and_non_error_non(self): """ Scoped and non-scoped fields, with non-scoped error """ test_pr = { 'synopsis': 'foo', 'identifier': [ (1, { 'scoped-enum-fld': 'foo' }), ], } self.vf_out = [[], [1]] out = self.db._validate(test_pr, 'fields') self.assertEqual(self.fname_in, 'synopsis scoped-enum-fld'.split()) self.assertEqual(out, { 'synopsis': [1], }) def test_12_skips_read_only(self): """ skips read-only fields """ test_pr = { 'synopsis': 'foo', 'last-modified': 'bar', } self.vf_out = [[]] out = self.db._validate(test_pr, 'fields') self.assertEqual(self.fname_in, ['synopsis']) self.assertEqual(out, {}) def test_13_all_fields(self): """ all fields """ test_pr = { 'synopsis': 'foo', 'last-modified': 'bar', 'identifier': [ (1, { 'scoped-enum-fld': 'foo' }), ], } self.vf_out = [ [], [], [], [], [], ] out = self.db._validate(test_pr, 'all') self.assertEqual( self.fname_in, 'synopsis enum-fld multienum-fld multitext-fld scoped-enum-fld'. split()) self.assertEqual(out, {}) def test_14_all_fields_errors(self): """ all fields, with errors """ test_pr = { 'synopsis': 'foo', 'last-modified': 'bar', 'identifier': [ (1, { 'scoped-enum-fld': 'foo' }), ], } self.vf_out = [ [1], [2], [], [], [], ] out = self.db._validate(test_pr, 'all') self.assertEqual( self.fname_in, 'synopsis enum-fld multienum-fld multitext-fld scoped-enum-fld'. split()) self.assertEqual(out, { 'multitext-fld': [2], 'scoped-enum-fld{1}': [1], })
class T04_Edit_pr(unittest.TestCase): """ edit_pr() """ def setUp(self): unittest.TestCase.setUp(self) self.server = gnats.Server('somehost') self.conn = FakeServerConnectionForDB(self.server) self.db = Database(self.server, 'testdb', self.conn) self.dbh = self.db.get_handle('user', 'pass', self.conn) self.edit = self.dbh.edit_pr self.conn.edit = self.my_edit self.prnum_in = '' self.db.unparse_pr = self.my_unparse_pr self.unp_in = {} self.conn.editaddr = self.my_editaddr self.addr_in = '' self.dbh.get_pr = self.my_get_pr # Synopsis Enum-fld Scoped-Enum-fld MultiEnum-fld Multitext-fld self.curr_pr = {'synopsis': 'foo bar', 'enum-fld': 'sw-tools', 'multienum-fld': 'tools', 'multitext-fld': 'a value', 'identifier': [(1, {'scoped-enum-fld': 'open'})],} def my_edit(self, prnum, pr): self.prnum_in = prnum return 'Ok.' def my_unparse_pr(self, pr): self.unp_in = pr return 'foo' def my_editaddr(self, addr): return 'Ok.' def my_get_pr(self, prnum, field_names='all'): return self.curr_pr def test_01_raises_no_pr(self): """ Raises if no pr supplied """ self.assertRaises(gnats.GnatsException, self.edit, 1234, None, 'user') def test_02_raises_no_prnum(self): """ Raises if no prnum supplied """ self.assertRaises(gnats.GnatsException, self.edit, '', {1:1}, 'user') def test_03_raises_no_user_address(self): """ Raises if no user_address supplied """ self.assertRaises(gnats.GnatsException, self.edit, 1234, {1:1}, '') def test_04_calls_editaddr(self): """ editaddr is called correctly """ def ea(addr): self.addr_in = addr raise TestExc() self.conn.editaddr = ea self.assertRaises(TestExc, self.edit, 1234, {'synopsis':1}, 'user') self.assertEqual(self.addr_in, 'user') def test_04a_calls_get_pr(self): """ get_pr is called with prnum and writeable fields """ def gp(prnum, field_names): self.prnum_in = prnum self.unp_in = field_names raise TestExc() self.dbh.get_pr = gp self.assertRaises(TestExc, self.edit, 1234, {'synopsis':1}, 'user') self.assertEqual(self.prnum_in, '1234') self.assertEqual(self.unp_in, ['synopsis', 'enum-fld', 'scoped-enum-fld', 'multienum-fld', 'multitext-fld', 'last-modified', 'reply-to:', 'from:',]) def test_05_checks_last_modified_diff(self): """ Raises if last_modified differs """ self.curr_pr['last-modified'] = 'foo' self.assertRaises(gnats.LastModifiedTimeException, self.edit, 1234, {'last-modified': 'bar', 'synopsis':1}, 'user') def test_06_checks_last_modified_same(self): """ OK if last_modified the same """ self.curr_pr['last-modified'] = 'bar' self.edit(1234, {'last-modified': 'bar', 'synopsis':1}, 'user') # The call to edit() will raise if things aren't right... def test_07_adds_number(self): """ Adds number field to pr dict """ self.edit(1234, {'synopsis': 'boo'}, 'user') self.assertEqual(self.unp_in['number'], '1234') def test_07_interleaves_non_scoped(self): """ Correctly interleaves non-scoped field data """ self.edit(1234, {'synopsis': 'boo'}, 'user') self.assertEqual(self.unp_in, {'synopsis': 'boo', 'enum-fld': 'sw-tools', 'multienum-fld': 'tools', 'multitext-fld': 'a value', 'identifier': [(1, {'scoped-enum-fld': 'open'})], 'number': '1234',}) def test_08_interleaves_scoped(self): """ Correctly interleaves existing scoped field data """ self.edit(1234, {'identifier': [(1, {'scoped-enum-fld': 'boo'})]}, 'x') self.assertEqual(self.unp_in, {'synopsis': 'foo bar', 'enum-fld': 'sw-tools', 'multienum-fld': 'tools', 'multitext-fld': 'a value', 'identifier': [(1, {'scoped-enum-fld': 'boo'})], 'number': '1234',}) def test_09_interleaves_new_scope(self): """ Correctly interleaves a new scope """ self.edit(1234, {'identifier': [(2, {'scoped-enum-fld': 'boo'})]}, 'x') self.assertEqual(self.unp_in, {'synopsis': 'foo bar', 'enum-fld': 'sw-tools', 'multienum-fld': 'tools', 'multitext-fld': 'a value', 'identifier': [(2, {'scoped-enum-fld': 'boo'}), (1, {'scoped-enum-fld': 'open'})], 'number': '1234',}) def test_10_envelope_fields(self): """ Correctly interleaves envelope fields """ self.curr_pr['from:'] = 'wow' self.edit(1234, {'from:': 'fred'}, 'x') self.assertEqual(self.unp_in, {'synopsis': 'foo bar', 'enum-fld': 'sw-tools', 'multienum-fld': 'tools', 'multitext-fld': 'a value', 'identifier': [(1, {'scoped-enum-fld': 'open'})], 'number': '1234', 'from:': 'fred',}) def test_11_removes_scope(self): """ Scope is stripped off the PR number """ self.edit('1234-1', {'from:': 'fred'}, 'x') self.assertEqual(self.prnum_in, '1234') def gp(prnum, field_names): self.prnum_in = prnum self.unp_in = field_names raise TestExc() self.dbh.get_pr = gp self.assertRaises(TestExc, self.edit, '1234-1', {'from:': 'fred'}, 'user') self.assertEqual(self.prnum_in, '1234') def test_12_honors_really_read_only_non_scoped(self): """ Honors _really_read_only flag """ self.db.fields['synopsis'].read_only = True self.edit(1234, {'enum-fld': 'boo'}, 'user') self.assertEqual(self.unp_in['synopsis'], 'foo bar') def test_13_honors_really_read_only_scoped(self): """ Honors _really_read_only flag """ self.db.fields['scoped-enum-fld'].read_only = True self.edit(1234, {'enum-fld': 'boo'}, 'user') self.assertEqual(self.unp_in['identifier'][0][1]['scoped-enum-fld'], 'open') def test_14_skips_table_fields(self): """ Skips table-fields when fetching current PR """ def gp(prnum, field_names): self.prnum_in = prnum self.unp_in = field_names raise TestExc() self.dbh.get_pr = gp self.db.fields['change-log'].read_only = False self.db.fields['change-log']._really_read_only = False self.assertRaises(TestExc, self.edit, 1234, {'change-log':'foo'}, 'user') self.assertEqual(self.prnum_in, '1234') self.assertEqual(self.unp_in, ['synopsis', 'enum-fld', 'scoped-enum-fld', 'multienum-fld', 'multitext-fld', 'last-modified', 'reply-to:', 'from:',]) def test_15_skips_table_fields(self): """ Skips not-really-read-only table-field when filling in from curr PR """ self.db.fields['change-log'].read_only = True self.db.fields['change-log']._really_read_only = False self.edit(1234, {'synopsis': 'boo'}, 'user') self.assertEqual(self.unp_in['synopsis'], 'boo')
class T06_Validate(unittest.TestCase): """ _validate """ def setUp(self): unittest.TestCase.setUp(self) server = gnats.Server('somehost') conn = FakeServerConnectionForDB(server) self.db = Database(server, 'testdb', conn) self.db.validate_field = self.my_validate_field self.fname_in = [] self.pr_in = [] self.check_cr_in = [] self.vf_out = [] def my_validate_field(self, fname, pr, check_cr=False): self.fname_in.append(fname) self.pr_in.append(pr) self.check_cr_in.append(check_cr) return self.vf_out.pop() def test_01_initial(self): """ initial entry fields """ test_pr = {'synopsis': 'foo', 'identifier': [(1, {'scoped-enum-fld': 'foo'}),], } self.vf_out = [[], [], [], []] out = self.db._validate(test_pr, 'initial') self.assertEqual(self.fname_in, 'synopsis enum-fld multitext-fld from:'.split()) self.assertEqual(out, {}) def test_02_initial_errors(self): """ initial entry fields with errors """ test_pr = {'synopsis': 'foo', 'identifier': [(1, {'scoped-enum-fld': 'foo'}),], } self.vf_out = [[], [1], [], [2]] out = self.db._validate(test_pr, 'initial') self.assertEqual(self.fname_in, 'synopsis enum-fld multitext-fld from:'.split()) self.assertEqual(out, {'synopsis': [2], 'multitext-fld': [1],}) def test_03_non_scoped(self): """ non-scoped fields """ test_pr = {'synopsis': 'foo', 'enum-fld': 'bar',} self.vf_out = [[], []] out = self.db._validate(test_pr, 'fields') self.assertEqual(self.fname_in, 'synopsis enum-fld'.split()) self.assertEqual(out, {}) def test_04_non_scoped_errors(self): """ non-scoped fields with errors """ test_pr = {'synopsis': 'foo', 'enum-fld': 'bar',} self.vf_out = [[1], []] out = self.db._validate(test_pr, 'fields') self.assertEqual(self.fname_in, 'synopsis enum-fld'.split()) self.assertEqual(out, {'enum-fld': [1],}) def test_05_scoped(self): """ scoped fields only """ test_pr = {'identifier': [(1, {'scoped-enum-fld': 'foo'}),],} self.vf_out = [[], []] out = self.db._validate(test_pr, 'fields') self.assertEqual(self.fname_in, 'scoped-enum-fld'.split()) self.assertEqual(out, {}) def test_06_scoped_error(self): """ scoped fields only, with error """ test_pr = {'identifier': [(1, {'scoped-enum-fld': 'foo'}),],} self.vf_out = [[1]] out = self.db._validate(test_pr, 'fields') self.assertEqual(self.fname_in, ['scoped-enum-fld']) self.assertEqual(out, {'scoped-enum-fld{1}': [1],}) def test_07_non_scoped_change_reason(self): """ non-scoped fields with change-reason """ test_pr = {'synopsis': 'foo', 'enum-fld': 'bar',} self.vf_out = [[], []] out = self.db._validate(test_pr, 'fields-cr') self.assertEqual(self.fname_in, 'synopsis enum-fld'.split()) self.assertEqual(out, {}) self.assertEqual(self.check_cr_in, [True, True]) def test_08_scoped_change_reason(self): """ scoped fields only, with change-reason""" test_pr = {'identifier': [(1, {'scoped-enum-fld': 'foo'}),],} self.vf_out = [[], []] out = self.db._validate(test_pr, 'fields-cr') self.assertEqual(self.fname_in, 'scoped-enum-fld'.split()) self.assertEqual(out, {}) self.assertEqual(self.check_cr_in, [True]) def test_09_scoped_and_non(self): """ Scoped and non-scoped fields """ test_pr = {'synopsis': 'foo', 'identifier': [(1, {'scoped-enum-fld': 'foo'}),], } self.vf_out = [[], []] out = self.db._validate(test_pr, 'fields') self.assertEqual(self.fname_in, 'synopsis scoped-enum-fld'.split()) self.assertEqual(out, {}) def test_10_scoped_and_non_error_scoped(self): """ Scoped and non-scoped fields, with scoped error """ test_pr = {'synopsis': 'foo', 'identifier': [(1, {'scoped-enum-fld': 'foo'}),], } self.vf_out = [[1], []] out = self.db._validate(test_pr, 'fields') self.assertEqual(self.fname_in, 'synopsis scoped-enum-fld'.split()) self.assertEqual(out, {'scoped-enum-fld{1}': [1],}) def test_11_scoped_and_non_error_non(self): """ Scoped and non-scoped fields, with non-scoped error """ test_pr = {'synopsis': 'foo', 'identifier': [(1, {'scoped-enum-fld': 'foo'}),], } self.vf_out = [[], [1]] out = self.db._validate(test_pr, 'fields') self.assertEqual(self.fname_in, 'synopsis scoped-enum-fld'.split()) self.assertEqual(out, {'synopsis': [1],}) def test_12_skips_read_only(self): """ skips read-only fields """ test_pr = {'synopsis': 'foo', 'last-modified': 'bar',} self.vf_out = [[]] out = self.db._validate(test_pr, 'fields') self.assertEqual(self.fname_in, ['synopsis']) self.assertEqual(out, {}) def test_13_all_fields(self): """ all fields """ test_pr = {'synopsis': 'foo', 'last-modified': 'bar', 'identifier': [(1, {'scoped-enum-fld': 'foo'}),],} self.vf_out = [[], [], [], [], [],] out = self.db._validate(test_pr, 'all') self.assertEqual(self.fname_in, 'synopsis enum-fld multienum-fld multitext-fld scoped-enum-fld'.split()) self.assertEqual(out, {}) def test_14_all_fields_errors(self): """ all fields, with errors """ test_pr = {'synopsis': 'foo', 'last-modified': 'bar', 'identifier': [(1, {'scoped-enum-fld': 'foo'}),],} self.vf_out = [[1], [2], [], [], [],] out = self.db._validate(test_pr, 'all') self.assertEqual(self.fname_in, 'synopsis enum-fld multienum-fld multitext-fld scoped-enum-fld'.split()) self.assertEqual(out, {'multitext-fld': [2], 'scoped-enum-fld{1}': [1],})
class T05_ValidateField(unittest.TestCase): """ validate_field() """ def setUp(self): unittest.TestCase.setUp(self) server = gnats.Server('somehost') conn = FakeServerConnectionForDB(server) self.db = Database(server, 'testdb', conn) def test_01_field_raises_on_invalid(self): """ validate_field raises on invalid field """ self.assertRaises(gnats.InvalidFieldNameException, self.db.validate_field, 'not-valid', {}) def test_02_field_required_absent(self): """ validate_field complains on absent required value """ out = self.db.validate_field('synopsis', {}) self.assertTrue(len(out) == 1) self.assertTrue(out[0].lower().find('required') > -1) def test_03_field_required_blank(self): """ validate_field complains on blank required value """ out = self.db.validate_field('synopsis', {'synopsis': ''}) self.assertTrue(len(out) == 1) self.assertTrue(out[0].lower().find('required') > -1) def test_04_field_required_present(self): """ validate_field finds required value """ out = self.db.validate_field('synopsis', {'synopsis': 'foo'}) self.assertTrue(len(out) == 0) def test_05_field_enum_invalid(self): """ validate_field complains about invalid enum """ out = self.db.validate_field('enum-fld', {'enum-fld': 'foo',}) self.assertTrue(len(out) == 1) self.assertTrue(out[0].lower().find('illegal') > -1) def test_06_field_enum_valid(self): """ validate_field accepts valid enum """ out = self.db.validate_field('enum-fld', {'enum-fld': 'cat1',}) self.assertTrue(len(out) == 0) def test_07_field_enum_allow_any(self): """ validate_field honors allow_any_value """ self.db.fields['enum-fld'].allow_any_value = True out = self.db.validate_field('enum-fld', {'enum-fld': 'foo',}) self.assertTrue(len(out) == 0) def test_08_field_change_reason_missing(self): """ validate_field complains about missing change-reason """ out = self.db.validate_field('enum-fld', {'enum-fld': 'cat2',}, check_cr=True) self.assertTrue(len(out) == 1) self.assertTrue(out[0].lower().find('change reason') > -1) def test_09_field_change_reason_present(self): """ validate_field finds supplied change-reason """ out = self.db.validate_field('enum-fld', {'enum-fld': 'cat2', 'enum-fld-changed-why': 'foo',}, check_cr=True) self.assertTrue(len(out) == 0) def test_10_field_multienum_string(self): """ Valid multienum value supplied as string """ out = self.db.validate_field('multienum-fld', {'multienum-fld': 'product1:product2',}) self.assertTrue(len(out) == 0) def test_11_field_bad_multienum_string(self): """ Invalid multienum value supplied as string """ out = self.db.validate_field('multienum-fld', {'multienum-fld': 'productX:product2',}) self.assertTrue(out[0].find('productX') > -1) def test_12_field_multienum_list(self): """ Valid multienum value supplied as list """ out = self.db.validate_field('multienum-fld', {'multienum-fld': 'product1 product2'.split(),}) self.assertTrue(len(out) == 0) def test_13_field_bad_multienum_list(self): """ Invalid multienum value supplied as list """ out = self.db.validate_field('multienum-fld', {'multienum-fld': 'product1 productY'.split(),}) self.assertTrue(out[0].find('productY') > -1) def test_14_field__multienum_bad_input_type(self): """ Multienum value supplied as non-list, non-string """ out = self.db.validate_field('multienum-fld', {'multienum-fld': 1234,}) self.assertTrue(out[0].find('neither') > -1)