diff options
author | Jason Kirtland <jek@discorporate.us> | 2008-05-14 22:09:23 +0000 |
---|---|---|
committer | Jason Kirtland <jek@discorporate.us> | 2008-05-14 22:09:23 +0000 |
commit | dd20ca5cb9eb0361f22023437d25a5bbb53f6871 (patch) | |
tree | f033f05e3a273456d7e6100ce1897ba89849168f | |
parent | b2504db4f72e64981f27b796fcfd50c3c07fd606 (diff) | |
download | sqlalchemy-dd20ca5cb9eb0361f22023437d25a5bbb53f6871.tar.gz |
- Removed @unsupported
-rw-r--r-- | test/engine/execute.py | 2 | ||||
-rw-r--r-- | test/engine/reflection.py | 4 | ||||
-rw-r--r-- | test/engine/transaction.py | 32 | ||||
-rw-r--r-- | test/orm/assorted_eager.py | 2 | ||||
-rw-r--r-- | test/orm/generative.py | 2 | ||||
-rw-r--r-- | test/orm/query.py | 3 | ||||
-rw-r--r-- | test/orm/session.py | 12 | ||||
-rw-r--r-- | test/orm/unitofwork.py | 3 | ||||
-rw-r--r-- | test/sql/defaults.py | 2 | ||||
-rw-r--r-- | test/sql/query.py | 36 | ||||
-rw-r--r-- | test/sql/quote.py | 23 | ||||
-rw-r--r-- | test/sql/testtypes.py | 3 | ||||
-rw-r--r-- | test/testlib/requires.py | 108 | ||||
-rw-r--r-- | test/testlib/testing.py | 47 |
14 files changed, 166 insertions, 113 deletions
diff --git a/test/engine/execute.py b/test/engine/execute.py index 5a42c2dd0..80f4e390c 100644 --- a/test/engine/execute.py +++ b/test/engine/execute.py @@ -49,7 +49,7 @@ class ExecuteTest(TestBase): # pyformat is supported for mysql, but skipping because a few driver # versions have a bug that bombs out on this test. (1.2.2b3, 1.2.2c1, 1.2.2) - @testing.unsupported('mysql', 'supported but not covered for MySQLdb') + @testing.skip_if(lambda: testing.against('mysql'), 'db-api flaky') @testing.fails_on_everything_except('postgres') def test_raw_python(self): for conn in (testing.db, testing.db.connect()): diff --git a/test/engine/reflection.py b/test/engine/reflection.py index ebb79154e..3995fdedc 100644 --- a/test/engine/reflection.py +++ b/test/engine/reflection.py @@ -418,7 +418,7 @@ class ReflectionTest(TestBase, ComparesTables): meta.drop_all() - @testing.unsupported('oracle', 'FIXME: unknown, confirm not fails_on') + @testing.crashes('oracle', 'FIXME: unknown, confirm not fails_on') def testreserved(self): # check a table that uses an SQL reserved name doesn't cause an error meta = MetaData(testing.db) @@ -676,7 +676,7 @@ class SchemaTest(TestBase): assert buf.index("CREATE TABLE someschema.table1") > -1 assert buf.index("CREATE TABLE someschema.table2") > -1 - @testing.unsupported('firebird', 'FIXME: unknown- no schema support in db?') + @testing.crashes('firebird', 'FIXME: unknown- no schema support in db?') @testing.fails_on('sqlite') # fixme: revisit these below. @testing.fails_on('access', 'oracle', 'mssql', 'sybase') diff --git a/test/engine/transaction.py b/test/engine/transaction.py index 50d38d699..69d35748b 100644 --- a/test/engine/transaction.py +++ b/test/engine/transaction.py @@ -732,11 +732,11 @@ class ForUpdateTest(TestBase): break con.close() - @testing.unsupported('sqlite', 'needs n threads -> 1 :memory: db') - @testing.unsupported('mssql', 'FIXME: unknown') - @testing.unsupported('firebird', 'FIXME: unknown') - @testing.unsupported('sybase', 'FIXME: unknown') - @testing.unsupported('access', 'FIXME: unknown') + @testing.crashes('mssql', 'FIXME: unknown') + @testing.crashes('firebird', 'FIXME: unknown') + @testing.crashes('sybase', 'FIXME: unknown') + @testing.crashes('access', 'FIXME: unknown') + @testing.requires.independent_connections def test_queued_update(self): """Test SELECT FOR UPDATE with concurrent modifications. @@ -798,11 +798,11 @@ class ForUpdateTest(TestBase): return errors - @testing.unsupported('sqlite', 'needs n threads -> 1 memory db') - @testing.unsupported('mssql', 'FIXME: unknown') - @testing.unsupported('firebird', 'FIXME: unknown') - @testing.unsupported('sybase', 'FIXME: unknown') - @testing.unsupported('access', 'FIXME: unknown') + @testing.crashes('mssql', 'FIXME: unknown') + @testing.crashes('firebird', 'FIXME: unknown') + @testing.crashes('sybase', 'FIXME: unknown') + @testing.crashes('access', 'FIXME: unknown') + @testing.requires.independent_connections def test_queued_select(self): """Simple SELECT FOR UPDATE conflict test""" @@ -811,12 +811,12 @@ class ForUpdateTest(TestBase): sys.stderr.write("Failure: %s\n" % e) self.assert_(len(errors) == 0) - @testing.unsupported('sqlite', 'needs n threads -> 1 memory db') - @testing.unsupported('mssql', 'FIXME: unknown') - @testing.unsupported('mysql', 'no support for NOWAIT') - @testing.unsupported('firebird', 'FIXME: unknown') - @testing.unsupported('sybase', 'FIXME: unknown') - @testing.unsupported('access', 'FIXME: unknown') + @testing.crashes('mssql', 'FIXME: unknown') + @testing.fails_on('mysql') # no support for NOWAIT + @testing.crashes('firebird', 'FIXME: unknown') + @testing.crashes('sybase', 'FIXME: unknown') + @testing.crashes('access', 'FIXME: unknown') + @testing.requires.independent_connections def test_nowait_select(self): """Simple SELECT FOR UPDATE NOWAIT conflict test""" diff --git a/test/orm/assorted_eager.py b/test/orm/assorted_eager.py index 76fcd869d..ab59d5a44 100644 --- a/test/orm/assorted_eager.py +++ b/test/orm/assorted_eager.py @@ -178,7 +178,7 @@ class EagerTest(_base.MappedTest): result = ["%d %s" % ( t.id,t.category.name ) for t in l] eq_(result, [u'1 Some Category', u'3 Some Category']) - @testing.unsupported('sybase', 'FIXME: unknown, verify not fails_on') + @testing.crashes('sybase', 'FIXME: unknown, verify not fails_on') @testing.resolve_artifact_names def test_without_outerjoin_literal(self): s = create_session() diff --git a/test/orm/generative.py b/test/orm/generative.py index 3fcbf2918..652823b28 100644 --- a/test/orm/generative.py +++ b/test/orm/generative.py @@ -35,7 +35,7 @@ class GenerativeQueryTest(_base.MappedTest): assert res.order_by([Foo.bar])[0].bar == 5 assert res.order_by([sa.desc(Foo.bar)])[0].bar == 95 - @testing.unsupported('mssql', 'FIXME: verify not fails_on()') + @testing.crashes('mssql', 'FIXME: verify not fails_on()') @testing.fails_on('maxdb') @testing.resolve_artifact_names def test_slice(self): diff --git a/test/orm/query.py b/test/orm/query.py index d2550427c..911155692 100644 --- a/test/orm/query.py +++ b/test/orm/query.py @@ -16,6 +16,7 @@ from orm import _fixtures from sqlalchemy.orm.util import join, outerjoin, with_parent + class QueryTest(FixtureTest): keep_mappers = True keep_data = True @@ -414,7 +415,7 @@ class FilterTest(QueryTest): assert [User(id=10)] == sess.query(User).outerjoin("addresses", aliased=True).filter(~User.addresses.any()).all() - @testing.unsupported('maxdb', 'can dump core') + @testing.crashes('maxdb', 'can dump core') def test_has(self): sess = create_session() assert [Address(id=5)] == sess.query(Address).filter(Address.user.has(name='fred')).all() diff --git a/test/orm/session.py b/test/orm/session.py index 3eaa2ec29..058548e2c 100644 --- a/test/orm/session.py +++ b/test/orm/session.py @@ -151,8 +151,8 @@ class SessionTest(_fixtures.FixtureTest): assert len(session.query(User).filter_by(name='Johnny').all()) == 0 session.close() - @testing.unsupported('mssql', 'test causes mssql to hang') - @testing.unsupported('sqlite', 'needs true independent connections') + @testing.crashes('mssql', 'test causes mssql to hang') + @testing.requires.independent_connections @engines.close_open_connections @testing.resolve_artifact_names def test_transaction(self): @@ -171,8 +171,8 @@ class SessionTest(_fixtures.FixtureTest): assert testing.db.connect().execute("select count(1) from users").scalar() == 1 sess.close() - @testing.unsupported('mssql', 'test causes mssql to hang') - @testing.unsupported('sqlite', 'needs true independent connections') + @testing.crashes('mssql', 'test causes mssql to hang') + @testing.requires.independent_connections @engines.close_open_connections @testing.resolve_artifact_names def test_autoflush(self): @@ -206,8 +206,8 @@ class SessionTest(_fixtures.FixtureTest): eq_(sess.query(Address).filter(Address.user==u).one(), Address(email_address='foo')) - @testing.unsupported('mssql', 'test causes mssql to hang') - @testing.unsupported('sqlite', 'needs true independent connections') + @testing.crashes('mssql', 'test causes mssql to hang') + @testing.requires.independent_connections @engines.close_open_connections @testing.resolve_artifact_names def test_autoflush_unbound(self): diff --git a/test/orm/unitofwork.py b/test/orm/unitofwork.py index a6ff5cc76..a05a7aa51 100644 --- a/test/orm/unitofwork.py +++ b/test/orm/unitofwork.py @@ -16,6 +16,7 @@ from orm import _base, _fixtures from engine import _base as engine_base import pickleable + class UnitOfWorkTest(object): pass @@ -658,7 +659,7 @@ class ClauseAttributesTest(_base.MappedTest): eq_(u.name, 'test2') eq_(u.counter, 2) - @testing.unsupported('mssql', 'FIXME: unknown, verify not fails_on()') + @testing.crashes('mssql', 'FIXME: unknown, verify not fails_on()') @testing.resolve_artifact_names def test_insert(self): u = User(name='test', counter=sa.select([5])) diff --git a/test/sql/defaults.py b/test/sql/defaults.py index dafab1fd0..8beb016ab 100644 --- a/test/sql/defaults.py +++ b/test/sql/defaults.py @@ -385,7 +385,7 @@ class PKDefaultTest(TestBase): def tearDownAll(self): metadata.drop_all() - @testing.unsupported('mssql', 'FIXME: unknown, verify not fails_on') + @testing.crashes('mssql', 'FIXME: unknown, verify not fails_on') def test_basic(self): t2.insert().execute(nextid=1) r = t1.insert().execute(data='hi') diff --git a/test/sql/query.py b/test/sql/query.py index 098e709b2..2dad9c695 100644 --- a/test/sql/query.py +++ b/test/sql/query.py @@ -296,7 +296,7 @@ class QueryTest(TestBase): r = users.select(limit=3, order_by=[users.c.user_id]).execute().fetchall() self.assert_(r == [(1, 'john'), (2, 'jack'), (3, 'ed')], repr(r)) - @testing.unsupported('mssql', 'FIXME: guessing') + @testing.crashes('mssql', 'FIXME: guessing') @testing.fails_on('maxdb') def test_select_limit_offset(self): users.insert().execute(user_id=1, user_name='john') @@ -492,9 +492,9 @@ class QueryTest(TestBase): self.assertEqual([x.lower() for x in r.keys()], ['user_name', 'user_id']) self.assertEqual(r.values(), ['foo', 1]) - @testing.unsupported('oracle', 'FIXME: unknown, varify not fails_on()') - @testing.unsupported('firebird', 'FIXME: unknown, verify not fails_on()') - @testing.unsupported('maxdb', 'FIXME: unknown, verify not fails_on()') + @testing.crashes('oracle', 'FIXME: unknown, varify not fails_on()') + @testing.crashes('firebird', 'FIXME: unknown, verify not fails_on()') + @testing.crashes('maxdb', 'FIXME: unknown, verify not fails_on()') def test_column_accessor_shadow(self): meta = MetaData(testing.db) shadowed = Table('test_shadowed', meta, @@ -668,7 +668,7 @@ class CompoundTest(TestBase): ('ccc', 'aaa')] self.assertEquals(u.alias('bar').select().execute().fetchall(), wanted) - @testing.unsupported('oracle', 'FIXME: unknown, verify not fails_on') + @testing.crashes('oracle', 'FIXME: unknown, verify not fails_on') @testing.fails_on('mysql') @testing.fails_on('sqlite') def test_union_all(self): @@ -687,8 +687,8 @@ class CompoundTest(TestBase): found2 = self._fetchall_sorted(e.alias('foo').select().execute()) self.assertEquals(found2, wanted) - @testing.unsupported('firebird', 'FIXME: unknown, verify not fails_on') - @testing.unsupported('sybase', 'FIXME: unknown, verify not fails_on') + @testing.crashes('firebird', 'FIXME: unknown, verify not fails_on') + @testing.crashes('sybase', 'FIXME: unknown, verify not fails_on') @testing.fails_on('mysql') def test_intersect(self): i = intersect( @@ -704,9 +704,9 @@ class CompoundTest(TestBase): found2 = self._fetchall_sorted(i.alias('bar').select().execute()) self.assertEquals(found2, wanted) - @testing.unsupported('firebird', 'FIXME: unknown, verify not fails_on') - @testing.unsupported('oracle', 'FIXME: unknown, verify not fails_on') - @testing.unsupported('sybase', 'FIXME: unknown, verify not fails_on') + @testing.crashes('firebird', 'FIXME: unknown, verify not fails_on') + @testing.crashes('oracle', 'FIXME: unknown, verify not fails_on') + @testing.crashes('sybase', 'FIXME: unknown, verify not fails_on') @testing.fails_on('mysql') def test_except_style1(self): e = except_(union( @@ -721,9 +721,9 @@ class CompoundTest(TestBase): found = self._fetchall_sorted(e.alias('bar').select().execute()) self.assertEquals(found, wanted) - @testing.unsupported('firebird', 'FIXME: unknown, verify not fails_on') - @testing.unsupported('oracle', 'FIXME: unknown, verify not fails_on') - @testing.unsupported('sybase', 'FIXME: unknown, verify not fails_on') + @testing.crashes('firebird', 'FIXME: unknown, verify not fails_on') + @testing.crashes('oracle', 'FIXME: unknown, verify not fails_on') + @testing.crashes('sybase', 'FIXME: unknown, verify not fails_on') @testing.fails_on('mysql') def test_except_style2(self): e = except_(union( @@ -741,9 +741,9 @@ class CompoundTest(TestBase): found2 = self._fetchall_sorted(e.alias('bar').select().execute()) self.assertEquals(found2, wanted) - @testing.unsupported('firebird', 'FIXME: unknown, verify not fails_on') - @testing.unsupported('oracle', 'FIXME: unknown, verify not fails_on') - @testing.unsupported('sybase', 'FIXME: unknown, verify not fails_on') + @testing.crashes('firebird', 'FIXME: unknown, verify not fails_on') + @testing.crashes('oracle', 'FIXME: unknown, verify not fails_on') + @testing.crashes('sybase', 'FIXME: unknown, verify not fails_on') @testing.fails_on('mysql') @testing.fails_on('sqlite') def test_except_style3(self): @@ -759,7 +759,7 @@ class CompoundTest(TestBase): self.assertEquals(e.alias('foo').select().execute().fetchall(), [('ccc',)]) - @testing.unsupported('firebird', 'FIXME: unknown, verify not fails_on') + @testing.crashes('firebird', 'FIXME: unknown, verify not fails_on') @testing.fails_on('mysql') def test_composite(self): u = intersect( @@ -775,7 +775,7 @@ class CompoundTest(TestBase): self.assertEquals(found, wanted) - @testing.unsupported('firebird', 'FIXME: unknown, verify not fails_on') + @testing.crashes('firebird', 'FIXME: unknown, verify not fails_on') @testing.fails_on('mysql') def test_composite_alias(self): ua = intersect( diff --git a/test/sql/quote.py b/test/sql/quote.py index 2e5910c7b..7003ce834 100644 --- a/test/sql/quote.py +++ b/test/sql/quote.py @@ -4,11 +4,12 @@ from sqlalchemy import sql from sqlalchemy.sql import compiler from testlib import * + class QuoteTest(TestBase, AssertsCompiledSQL): def setUpAll(self): - # TODO: figure out which databases/which identifiers allow special characters to be used, - # such as: spaces, quote characters, punctuation characters, set up tests for those as - # well. + # TODO: figure out which databases/which identifiers allow special + # characters to be used, such as: spaces, quote characters, + # punctuation characters, set up tests for those as well. global table1, table2, table3 metadata = MetaData(testing.db) table1 = Table('WorstCase1', metadata, @@ -67,24 +68,24 @@ class QuoteTest(TestBase, AssertsCompiledSQL): res2 = select([table2.c.d123, table2.c.u123, table2.c.MixedCase], use_labels=True).execute().fetchall() print res2 assert(res2==[(1,2,3),(2,2,3),(4,3,2)]) - + def test_quote_flag(self): metadata = MetaData() - t1 = Table('TableOne', metadata, + t1 = Table('TableOne', metadata, Column('ColumnOne', Integer), schema="FooBar") self.assert_compile(t1.select(), '''SELECT "FooBar"."TableOne"."ColumnOne" FROM "FooBar"."TableOne"''') metadata = MetaData() - t1 = Table('t1', metadata, + t1 = Table('t1', metadata, Column('col1', Integer, quote=True), quote=True, schema="foo", quote_schema=True) self.assert_compile(t1.select(), '''SELECT "foo"."t1"."col1" FROM "foo"."t1"''') metadata = MetaData() - t1 = Table('TableOne', metadata, + t1 = Table('TableOne', metadata, Column('ColumnOne', Integer, quote=False), quote=False, schema="FooBar", quote_schema=False) self.assert_compile(t1.select(), '''SELECT FooBar.TableOne.ColumnOne FROM FooBar.TableOne''') - - @testing.unsupported('oracle', 'FIXME: unknown, verify not fails_on') + + @testing.crashes('oracle', 'FIXME: unknown, verify not fails_on') @testing.requires.subqueries def testlabels(self): """test the quoting of labels. @@ -109,12 +110,12 @@ class QuoteTest(TestBase, AssertsCompiledSQL): # note that 'foo' and 'FooCol' are literals already quoted x = select([sql.literal_column("'foo'").label("somelabel")], from_obj=[table]).alias("AnAlias") x = x.select() - self.assert_compile(x, + self.assert_compile(x, '''SELECT "AnAlias".somelabel FROM (SELECT 'foo' AS somelabel FROM "ImATable") AS "AnAlias"''') x = select([sql.literal_column("'FooCol'").label("SomeLabel")], from_obj=[table]) x = x.select() - self.assert_compile(x, + self.assert_compile(x, '''SELECT "SomeLabel" FROM (SELECT 'FooCol' AS "SomeLabel" FROM "ImATable")''') diff --git a/test/sql/testtypes.py b/test/sql/testtypes.py index 3e9f1d631..56bd61499 100644 --- a/test/sql/testtypes.py +++ b/test/sql/testtypes.py @@ -8,7 +8,6 @@ from sqlalchemy.databases import mssql, oracle, mysql, postgres, firebird from testlib import * - class AdaptTest(TestBase): def testadapt(self): e1 = url.URL('postgres').get_dialect()() @@ -381,7 +380,7 @@ class UnicodeTest(TestBase, AssertsExecutionResults): testing.db.engine.dialect.convert_unicode = prev_unicode testing.db.engine.dialect.convert_unicode = prev_assert - @testing.unsupported('oracle', 'FIXME: unknown, verify not fails_on') + @testing.crashes('oracle', 'FIXME: unknown, verify not fails_on') @testing.fails_on('firebird') # "Data type unknown" on the parameter def testlength(self): """checks the database correctly understands the length of a unicode string""" diff --git a/test/testlib/requires.py b/test/testlib/requires.py index 7c345ee6e..a382f42bc 100644 --- a/test/testlib/requires.py +++ b/test/testlib/requires.py @@ -6,64 +6,65 @@ target database. """ from testlib.testing import \ + _block_unconditionally as no_support, \ _chain_decorators_on, \ - exclude, \ - unsupported + exclude -def sequences(fn): - """Target database must support SEQUENCEs.""" +def deferrable_constraints(fn): + """Target database must support derferable constraints.""" return _chain_decorators_on( fn, - unsupported('access', 'no SEQUENCE support'), - unsupported('mssql', 'no SEQUENCE support'), - unsupported('mysql', 'no SEQUENCE support'), - unsupported('sqlite', 'no SEQUENCE support'), - unsupported('sybase', 'no SEQUENCE support'), + no_support('mysql', 'not supported by database'), + no_support('mssql', 'not supported by database'), ) -def savepoints(fn): - """Target database must support savepoints.""" +def foreign_keys(fn): + """Target database must support foreign keys.""" return _chain_decorators_on( fn, - unsupported('access', 'FIXME: guessing, needs confirmation'), - unsupported('mssql', 'FIXME: guessing, needs confirmation'), - unsupported('sqlite', 'not supported by database'), - unsupported('sybase', 'FIXME: guessing, needs confirmation'), - exclude('mysql', '<', (5, 0, 3), 'not supported by database'), + no_support('sqlite', 'not supported by database'), ) -def two_phase_transactions(fn): - """Target database must support two-phase transactions.""" +def independent_connections(fn): + """Target must support simultaneous, independent database connections.""" + + # This is also true of some configurations of UnixODBC and probably win32 + # ODBC as well. return _chain_decorators_on( fn, - unsupported('access', 'FIXME: guessing, needs confirmation'), - unsupported('firebird', 'no SA implementation'), - unsupported('maxdb', 'not supported by database'), - unsupported('mssql', 'FIXME: guessing, needs confirmation'), - unsupported('oracle', 'no SA implementation'), - unsupported('sqlite', 'not supported by database'), - unsupported('sybase', 'FIXME: guessing, needs confirmation'), - exclude('mysql', '<', (5, 0, 3), 'not supported by database'), + no_support('sqlite', 'no driver support') ) -def unicode_connections(fn): - """Target driver must support some encoding of Unicode across the wire.""" - # TODO: expand to exclude MySQLdb versions w/ broken unicode +def row_triggers(fn): + """Target must support standard statement-running EACH ROW triggers.""" return _chain_decorators_on( fn, - exclude('mysql', '<', (4, 1, 1), 'no unicode connection support'), + # no access to same table + exclude('mysql', '<', (5, 0, 10), 'not supported by database'), + no_support('postgres', 'not supported by database: no statements'), ) -def unicode_ddl(fn): - """Target driver must support some encoding of Unicode across the wire.""" - # TODO: expand to exclude MySQLdb versions w/ broken unicode +def savepoints(fn): + """Target database must support savepoints.""" return _chain_decorators_on( fn, - unsupported('maxdb', 'database support flakey'), - unsupported('oracle', 'FIXME: no support in database?'), - unsupported('sybase', 'FIXME: guessing, needs confirmation'), - exclude('mysql', '<', (4, 1, 1), 'no unicode connection support'), + no_support('access', 'FIXME: guessing, needs confirmation'), + no_support('mssql', 'FIXME: guessing, needs confirmation'), + no_support('sqlite', 'not supported by database'), + no_support('sybase', 'FIXME: guessing, needs confirmation'), + exclude('mysql', '<', (5, 0, 3), 'not supported by database'), + ) + +def sequences(fn): + """Target database must support SEQUENCEs.""" + return _chain_decorators_on( + fn, + no_support('access', 'no SEQUENCE support'), + no_support('mssql', 'no SEQUENCE support'), + no_support('mysql', 'no SEQUENCE support'), + no_support('sqlite', 'no SEQUENCE support'), + no_support('sybase', 'no SEQUENCE support'), ) def subqueries(fn): @@ -73,26 +74,35 @@ def subqueries(fn): exclude('mysql', '<', (4, 1, 1), 'no subquery support'), ) -def foreign_keys(fn): - """Target database must support foreign keys.""" +def two_phase_transactions(fn): + """Target database must support two-phase transactions.""" return _chain_decorators_on( fn, - unsupported('sqlite', 'not supported by database'), + no_support('access', 'FIXME: guessing, needs confirmation'), + no_support('firebird', 'no SA implementation'), + no_support('maxdb', 'not supported by database'), + no_support('mssql', 'FIXME: guessing, needs confirmation'), + no_support('oracle', 'no SA implementation'), + no_support('sqlite', 'not supported by database'), + no_support('sybase', 'FIXME: guessing, needs confirmation'), + exclude('mysql', '<', (5, 0, 3), 'not supported by database'), ) -def deferrable_constraints(fn): - """Target database must support derferable constraints.""" +def unicode_connections(fn): + """Target driver must support some encoding of Unicode across the wire.""" + # TODO: expand to exclude MySQLdb versions w/ broken unicode return _chain_decorators_on( fn, - unsupported('mysql', 'not supported by database'), - unsupported('mssql', 'not supported by database'), + exclude('mysql', '<', (4, 1, 1), 'no unicode connection support'), ) -def row_triggers(fn): - """Target must support standard statement-running EACH ROW triggers.""" +def unicode_ddl(fn): + """Target driver must support some encoding of Unicode across the wire.""" + # TODO: expand to exclude MySQLdb versions w/ broken unicode return _chain_decorators_on( fn, - # no access to same table - exclude('mysql', '<', (5, 0, 10), 'not supported by database'), - unsupported('postgres', 'not supported by database: no statements'), + no_support('maxdb', 'database support flakey'), + no_support('oracle', 'FIXME: no support in database?'), + no_support('sybase', 'FIXME: guessing, needs confirmation'), + exclude('mysql', '<', (4, 1, 1), 'no unicode connection support'), ) diff --git a/test/testlib/testing.py b/test/testlib/testing.py index c31e59156..c816963e4 100644 --- a/test/testlib/testing.py +++ b/test/testlib/testing.py @@ -147,13 +147,37 @@ def fails_on_everything_except(*dbs): return _function_named(maybe, fn_name) return decorate -def unsupported(db, reason): +def crashes(db, reason): """Mark a test as unsupported by a database implementation. - 'unsupported' tests will be skipped unconditionally. Useful for feature - tests that cause deadlocks or other fatal problems. + 'crashes' tests will be skipped unconditionally. Use for feature tests + that cause deadlocks or other fatal problems. + """ + carp = _should_carp_about_exclusion(reason) + def decorate(fn): + fn_name = fn.__name__ + def maybe(*args, **kw): + if config.db.name == db: + msg = "'%s' unsupported on DB implementation '%s': %s" % ( + fn_name, config.db.name, reason) + print msg + if carp: + print >> sys.stderr, msg + return True + else: + return fn(*args, **kw) + return _function_named(maybe, fn_name) + return decorate +def _block_unconditionally(db, reason): + """Mark a test as unsupported by a database implementation. + + Will never run the test against any version of the given database, ever, + no matter what. Use when your assumptions are infallible; past, present + and future. + + """ carp = _should_carp_about_exclusion(reason) def decorate(fn): fn_name = fn.__name__ @@ -170,6 +194,7 @@ def unsupported(db, reason): return _function_named(maybe, fn_name) return decorate + def exclude(db, op, spec, reason): """Mark a test as unsupported by specific database server versions. @@ -242,6 +267,22 @@ def _server_version(bind=None): bind = config.db return bind.dialect.server_version_info(bind.contextual_connect()) +def skip_if(predicate, reason=None): + """Skip a test if predicate is true.""" + reason = reason or predicate.__name__ + def decorate(fn): + fn_name = fn.__name__ + def maybe(*args, **kw): + if predicate(): + msg = "'%s' skipped on DB %s version '%s': %s" % ( + fn_name, config.db.name, _server_version(), reason) + print msg + return True + else: + return fn(*args, **kw) + return _function_named(maybe, fn_name) + return decorate + def emits_warning(*messages): """Mark a test as emitting a warning. |