def setUp(self):
     if not self.createdTables:
         self.createTables()
     self.createTables()
     self.dt = DatabaseTemplate(self.factory)
     self.dt.execute("DELETE FROM animal")
     self.dt.execute("DELETE FROM account")
     self.factory.commit()
     self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 0)
     self.transactionManager = ConnectionFactoryTransactionManager(self.factory)
     self.transactionTemplate = TransactionTemplate(self.transactionManager)
 def setUp(self):
     if not self.createdTables:
         self.createTables()
     self.createTables()
     self.dt = DatabaseTemplate(self.factory)
     self.dt.execute("DELETE FROM animal")
     self.dt.execute("DELETE FROM account")
     self.factory.commit()
     self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 0)
     self.transactionManager = ConnectionFactoryTransactionManager(self.factory)
     self.transactionTemplate = TransactionTemplate(self.transactionManager)
class AbstractTransactionTestCase(unittest.TestCase):

    def __init__(self, methodName='runTest'):
        unittest.TestCase.__init__(self, methodName)
        self.factory = None
        self.createdTables = False

    def setUp(self):
        if not self.createdTables:
            self.createTables()
        self.createTables()
        self.dt = DatabaseTemplate(self.factory)
        self.dt.execute("DELETE FROM animal")
        self.dt.execute("DELETE FROM account")
        self.factory.commit()
        self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 0)
        self.transactionManager = ConnectionFactoryTransactionManager(self.factory)
        self.transactionTemplate = TransactionTemplate(self.transactionManager)

    def tearDown(self):
        self.factory.getConnection().rollback()

    def testInsertingRowsIntoTheDatabase(self):
        rows = self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('black mamba',))
        self.assertEquals(rows, 1)

        name = self.dt.query_for_object("SELECT name FROM animal WHERE name = 'black mamba'", required_type=types.StringType)
        self.assertEquals(name, "black mamba")

    def testInsertingTwoRowsWithoutaTransactionButManuallyCommitted(self):
        self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('black mamba',))
        self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('copperhead',))
        self.factory.commit()
        self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 2)

    def testInsertingTwoRowsWithoutaTransactionButManuallyRolledBack(self):
        self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('black mamba',))
        self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('copperhead',))
        self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 2)
        self.dt.connection_factory.getConnection().rollback()
        self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 0)

    def testInsertingTwoRowsWithaTransactionAndNoErrorsAndNoResults(self):
        class txDefinition(TransactionCallbackWithoutResult):
            def do_in_tx_without_result(s, status):
                self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('black mamba',))
                self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('copperhead',))
                
        self.transactionTemplate.execute(txDefinition())
        self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 2)

    def testInsertingTwoRowsWithaTransactionAndAnIntermediateErrorAndNoResults(self):
        class txDefinition(TransactionCallbackWithoutResult):
            def do_in_tx_without_result(s, status):
                self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('black mamba',))
                self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 1)
                raise DataAccessException("This should break the transaction, and rollback the insert.")
                
        self.assertRaises(DataAccessException, self.transactionTemplate.execute, txDefinition())
        self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 0)

    def testInsertingTwoRowsWithaTransactionAndNoErrorsAndResults(self):
        class txDefinition(TransactionCallback):
            def do_in_transaction(s, status):
                self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('black mamba',))
                self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('copperhead',))
                results = self.dt.query_for_object("SELECT name FROM animal WHERE name like 'c%'", required_type=types.StringType)
                return results
                
        self.assertEquals(self.transactionTemplate.execute(txDefinition()), "copperhead")
        self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 2)

    def testInsertingTwoRowsWithaTransactionAndAnIntermediateErrorAndResults(self):
        class txDefinition(TransactionCallback):
            def do_in_transaction(s, status):
                self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('black mamba'))
                self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 1)
                raise DataAccessException("This should break the transaction, and rollback the insert.")
                
        self.assertRaises(DataAccessException, self.transactionTemplate.execute, txDefinition())
        self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 0)

    def testDeclarativeTransactions(self):
        appContext = ApplicationContext(DatabaseTxTestAppContext(self.factory))
        bank = appContext.get_object("bank")

        bank.open("Checking")
        bank.open("Savings")

        bank.deposit(125.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 125.00)

        bank.deposit(250.00, "Savings")
        self.assertEquals(bank.balance("Savings"), 250.00)

        bank.transfer(25.00, "Savings", "Checking")
        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 150.00)

        bank.withdraw(10.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 140.00)

        amount = 0.0
        try:
            amount = bank.withdraw(1000, "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass
        self.assertEquals(amount, 0.0)

        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 140.00)

        try:
            bank.transfer(200, "Checking", "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass

        self.assertEquals(bank.balance("Savings"), 225.00, "Bad transfer did NOT fail atomically!")
        self.assertEquals(bank.balance("Checking"), 140.00, "Bad transfer did NOT fail atomically!")

    def testDecoratorBasedTransactions(self):
        appContext = ApplicationContext(DatabaseTxTestDecorativeTransactions(self.factory))
        bank = appContext.get_object("bank")

        bank.open("Checking")
        bank.open("Savings")

        bank.deposit(125.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 125.00)

        bank.deposit(250.00, "Savings")
        self.assertEquals(bank.balance("Savings"), 250.00)

        bank.transfer(25.00, "Savings", "Checking")
        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 150.00)

        bank.withdraw(10.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 140.00)

        amount = 0.0
        try:
            amount = bank.withdraw(1000, "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass
        self.assertEquals(amount, 0.0)

        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 140.00)

        try:
            bank.transfer(200, "Checking", "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass
        self.assertEquals(bank.balance("Savings"), 225.00, "Bad transfer did NOT fail atomically!")
        self.assertEquals(bank.balance("Checking"), 140.00, "Bad transfer did NOT fail atomically!")

    def testDecoratorBasedTransactionsWithNoArguments(self):
        appContext = ApplicationContext(DatabaseTxTestDecorativeTransactionsWithNoArguments(self.factory))
        bank = appContext.get_object("bank")

        bank.open("Checking")
        bank.open("Savings")

        bank.deposit(125.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 125.00)

        bank.deposit(250.00, "Savings")
        self.assertEquals(bank.balance("Savings"), 250.00)

        bank.transfer(25.00, "Savings", "Checking")
        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 150.00)

        bank.withdraw(10.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 140.00)

        amount = 0.0
        try:
            amount = bank.withdraw(1000, "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass
        self.assertEquals(amount, 0.0)

        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 140.00)

        try:
            bank.transfer(200, "Checking", "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass

        self.assertEquals(bank.balance("Savings"), 225.00, "Bad transfer did NOT fail atomically!")
        self.assertEquals(bank.balance("Checking"), 140.00, "Bad transfer did NOT fail atomically!")
        
    def testDecoratorBasedTransactionsWithLotsOfArguments(self):
        appContext = ApplicationContext(DatabaseTxTestDecorativeTransactionsWithLotsOfArguments(self.factory))
        bank = appContext.get_object("bank")

        bank.open("Checking")
        bank.open("Savings")

        bank.deposit(125.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 125.00)

        bank.deposit(250.00, "Savings")
        self.assertEquals(bank.balance("Savings"), 250.00)

        bank.transfer(25.00, "Savings", "Checking")
        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 150.00)

        bank.withdraw(10.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 140.00)

        amount = 0.0
        try:
            amount = bank.withdraw(1000, "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass
        self.assertEquals(amount, 0.0)

        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 140.00)

        try:
            bank.transfer(200, "Checking", "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass

        self.assertEquals(bank.balance("Savings"), 225.00, "Bad transfer did NOT fail atomically!")
        logging.getLogger("springpythontest.databaseTransactionTestCases").debug(bank.balance("Checking"))
        self.assertEquals(bank.balance("Checking"), 140.00, "Bad transfer did NOT fail atomically!")
        
    def testOtherPropagationLevels(self):
        appContext = ApplicationContext(DatabaseTxTestDecorativeTransactionsWithLotsOfArguments(self.factory))
        bank = appContext.get_object("bank")

        # Call a mandatory operation outside a transaction, and verify it fails.
        try:
            bank.mandatoryOperation()
            self.fail("Expected a TransactionPropagationException!")
        except TransactionPropagationException:
            pass

        # Call a mandatory operation from within a transactional routine, and verify it works.
        bank.mandatoryOperationTransactionalWrapper()

        # Call a non-transactional operation from outside a transaction, and verify it works.
        bank.nonTransactionalOperation()

        # Call a non-tranactional operation from within a transaction, and verify it fails.
        try:
            bank.nonTransactionalOperationTransactionalWrapper()
            self.fail("Expected a TransactionPropagationException!")
        except TransactionPropagationException:
            pass

    def testTransactionProxyMethodFilters(self):
        appContext = ApplicationContext(DatabaseTxTestAppContext(self.factory))
        bank = appContext.get_object("bank")
 
        bank.open("Checking")
        bank.open("Savings")

        bank.deposit(125.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 125.00)

        bank.deposit(250.00, "Savings")
        self.assertEquals(bank.balance("Savings"), 250.00)

        bank.transfer(25.00, "Savings", "Checking")
        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 150.00)

        bank.withdraw(10.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 140.00)

        amount = 0.0
        try:
            amount = bank.withdraw(1000, "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass
        self.assertEquals(amount, 0.0)

        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 140.00)

        try:
            bank.transfer(200, "Checking", "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass

        self.assertEquals(bank.balance("Savings"), 225.00, "Bad transfer did NOT fail atomically!")
        self.assertEquals(bank.balance("Checking"), 140.00, "Bad transfer did NOT fail atomically!")
 
    def testTransactionalBankWithNoAutoTransactionalObject(self):
        appContext = ApplicationContext(DatabaseTxTestAppContextWithNoAutoTransactionalObject(self.factory))
        bank = appContext.get_object("bank")
 
        bank.open("Checking")
        bank.open("Savings")

        bank.deposit(125.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 125.00)

        bank.deposit(250.00, "Savings")
        self.assertEquals(bank.balance("Savings"), 250.00)

        bank.transfer(25.00, "Savings", "Checking")
        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 150.00)

        bank.withdraw(10.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 140.00)

        amount = 0.0
        try:
            amount = bank.withdraw(1000, "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass
        self.assertEquals(amount, 0.0)

        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 140.00)

        try:
            bank.transfer(200, "Checking", "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass

        self.assertEquals(bank.balance("Savings"), 225.00, "Bad transfer did NOT fail atomically!")
        self.assertEquals(bank.balance("Checking"), -60.00, "Bad transfer did NOT fail as expected (not atomically due to lack of AutoTransactionalObject)")
class AbstractTransactionTestCase(unittest.TestCase):

    def __init__(self, methodName='runTest'):
        unittest.TestCase.__init__(self, methodName)
        self.factory = None
        self.createdTables = False

    def setUp(self):
        if not self.createdTables:
            self.createTables()
        self.createTables()
        self.dt = DatabaseTemplate(self.factory)
        self.dt.execute("DELETE FROM animal")
        self.dt.execute("DELETE FROM account")
        self.factory.commit()
        self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 0)
        self.transactionManager = ConnectionFactoryTransactionManager(self.factory)
        self.transactionTemplate = TransactionTemplate(self.transactionManager)

    def tearDown(self):
        self.factory.getConnection().rollback()

    def testInsertingRowsIntoTheDatabase(self):
        rows = self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('black mamba',))
        self.assertEquals(rows, 1)

        name = self.dt.query_for_object("SELECT name FROM animal WHERE name = 'black mamba'", required_type=types.StringType)
        self.assertEquals(name, "black mamba")

    def testInsertingRowsIntoTheDatabaseWithInsertApi(self):
        id = self.dt.insert_and_return_id("INSERT INTO animal (name) VALUES (?)", ('black mamba',))
        self.assertEquals(id, 1)

        name = self.dt.query_for_object("SELECT name FROM animal WHERE name = 'black mamba'", required_type=types.StringType)
        self.assertEquals(name, "black mamba")

    def testInsertingTwoRowsWithoutaTransactionButManuallyCommitted(self):
        self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('black mamba',))
        self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('copperhead',))
        self.factory.commit()
        self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 2)

    def testInsertingTwoRowsWithoutaTransactionButManuallyRolledBack(self):
        self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('black mamba',))
        self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('copperhead',))
        self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 2)
        self.dt.connection_factory.getConnection().rollback()
        self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 0)

    def testInsertingTwoRowsWithaTransactionAndNoErrorsAndNoResults(self):
        class txDefinition(TransactionCallbackWithoutResult):
            def do_in_tx_without_result(s, status):
                self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('black mamba',))
                self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('copperhead',))
                
        self.transactionTemplate.execute(txDefinition())
        self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 2)

    def testInsertingTwoRowsWithaTransactionAndAnIntermediateErrorAndNoResults(self):
        class txDefinition(TransactionCallbackWithoutResult):
            def do_in_tx_without_result(s, status):
                self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('black mamba',))
                self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 1)
                raise DataAccessException("This should break the transaction, and rollback the insert.")
                
        self.assertRaises(DataAccessException, self.transactionTemplate.execute, txDefinition())
        self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 0)

    def testInsertingTwoRowsWithaTransactionAndNoErrorsAndResults(self):
        class txDefinition(TransactionCallback):
            def do_in_transaction(s, status):
                self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('black mamba',))
                self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('copperhead',))
                results = self.dt.query_for_object("SELECT name FROM animal WHERE name like 'c%'", required_type=types.StringType)
                return results
                
        self.assertEquals(self.transactionTemplate.execute(txDefinition()), "copperhead")
        self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 2)

    def testInsertingTwoRowsWithaTransactionAndAnIntermediateErrorAndResults(self):
        class txDefinition(TransactionCallback):
            def do_in_transaction(s, status):
                self.dt.execute("INSERT INTO animal (name) VALUES (?)", ('black mamba'))
                self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 1)
                raise DataAccessException("This should break the transaction, and rollback the insert.")
                
        self.assertRaises(DataAccessException, self.transactionTemplate.execute, txDefinition())
        self.assertEquals(len(self.dt.query_for_list("SELECT * FROM animal")), 0)

    def testDeclarativeTransactions(self):
        appContext = ApplicationContext(DatabaseTxTestAppContext(self.factory))
        bank = appContext.get_object("bank")

        bank.open("Checking")
        bank.open("Savings")

        bank.deposit(125.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 125.00)

        bank.deposit(250.00, "Savings")
        self.assertEquals(bank.balance("Savings"), 250.00)

        bank.transfer(25.00, "Savings", "Checking")
        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 150.00)

        bank.withdraw(10.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 140.00)

        amount = 0.0
        try:
            amount = bank.withdraw(1000, "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass
        self.assertEquals(amount, 0.0)

        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 140.00)

        try:
            bank.transfer(200, "Checking", "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass

        self.assertEquals(bank.balance("Savings"), 225.00, "Bad transfer did NOT fail atomically!")
        self.assertEquals(bank.balance("Checking"), 140.00, "Bad transfer did NOT fail atomically!")

    def testDecoratorBasedTransactions(self):
        appContext = ApplicationContext(DatabaseTxTestDecorativeTransactions(self.factory))
        bank = appContext.get_object("bank")

        bank.open("Checking")
        bank.open("Savings")

        bank.deposit(125.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 125.00)

        bank.deposit(250.00, "Savings")
        self.assertEquals(bank.balance("Savings"), 250.00)

        bank.transfer(25.00, "Savings", "Checking")
        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 150.00)

        bank.withdraw(10.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 140.00)

        amount = 0.0
        try:
            amount = bank.withdraw(1000, "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass
        self.assertEquals(amount, 0.0)

        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 140.00)

        try:
            bank.transfer(200, "Checking", "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass
        self.assertEquals(bank.balance("Savings"), 225.00, "Bad transfer did NOT fail atomically!")
        self.assertEquals(bank.balance("Checking"), 140.00, "Bad transfer did NOT fail atomically!")

    def testDecoratorBasedTransactionsWithNoArguments(self):
        appContext = ApplicationContext(DatabaseTxTestDecorativeTransactionsWithNoArguments(self.factory))
        bank = appContext.get_object("bank")

        bank.open("Checking")
        bank.open("Savings")

        bank.deposit(125.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 125.00)

        bank.deposit(250.00, "Savings")
        self.assertEquals(bank.balance("Savings"), 250.00)

        bank.transfer(25.00, "Savings", "Checking")
        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 150.00)

        bank.withdraw(10.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 140.00)

        amount = 0.0
        try:
            amount = bank.withdraw(1000, "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass
        self.assertEquals(amount, 0.0)

        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 140.00)

        try:
            bank.transfer(200, "Checking", "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass

        self.assertEquals(bank.balance("Savings"), 225.00, "Bad transfer did NOT fail atomically!")
        self.assertEquals(bank.balance("Checking"), 140.00, "Bad transfer did NOT fail atomically!")
        
    def testDecoratorBasedTransactionsWithLotsOfArguments(self):
        appContext = ApplicationContext(DatabaseTxTestDecorativeTransactionsWithLotsOfArguments(self.factory))
        bank = appContext.get_object("bank")

        bank.open("Checking")
        bank.open("Savings")

        bank.deposit(125.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 125.00)

        bank.deposit(250.00, "Savings")
        self.assertEquals(bank.balance("Savings"), 250.00)

        bank.transfer(25.00, "Savings", "Checking")
        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 150.00)

        bank.withdraw(10.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 140.00)

        amount = 0.0
        try:
            amount = bank.withdraw(1000, "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass
        self.assertEquals(amount, 0.0)

        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 140.00)

        try:
            bank.transfer(200, "Checking", "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass

        self.assertEquals(bank.balance("Savings"), 225.00, "Bad transfer did NOT fail atomically!")
        logging.getLogger("springpythontest.databaseTransactionTestCases").debug(bank.balance("Checking"))
        self.assertEquals(bank.balance("Checking"), 140.00, "Bad transfer did NOT fail atomically!")
        
    def testOtherPropagationLevels(self):
        appContext = ApplicationContext(DatabaseTxTestDecorativeTransactionsWithLotsOfArguments(self.factory))
        bank = appContext.get_object("bank")

        # Call a mandatory operation outside a transaction, and verify it fails.
        try:
            bank.mandatoryOperation()
            self.fail("Expected a TransactionPropagationException!")
        except TransactionPropagationException:
            pass

        # Call a mandatory operation from within a transactional routine, and verify it works.
        bank.mandatoryOperationTransactionalWrapper()

        # Call a non-transactional operation from outside a transaction, and verify it works.
        bank.nonTransactionalOperation()

        # Call a non-tranactional operation from within a transaction, and verify it fails.
        try:
            bank.nonTransactionalOperationTransactionalWrapper()
            self.fail("Expected a TransactionPropagationException!")
        except TransactionPropagationException:
            pass

    def testTransactionProxyMethodFilters(self):
        appContext = ApplicationContext(DatabaseTxTestAppContext(self.factory))
        bank = appContext.get_object("bank")
 
        bank.open("Checking")
        bank.open("Savings")

        bank.deposit(125.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 125.00)

        bank.deposit(250.00, "Savings")
        self.assertEquals(bank.balance("Savings"), 250.00)

        bank.transfer(25.00, "Savings", "Checking")
        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 150.00)

        bank.withdraw(10.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 140.00)

        amount = 0.0
        try:
            amount = bank.withdraw(1000, "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass
        self.assertEquals(amount, 0.0)

        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 140.00)

        try:
            bank.transfer(200, "Checking", "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass

        self.assertEquals(bank.balance("Savings"), 225.00, "Bad transfer did NOT fail atomically!")
        self.assertEquals(bank.balance("Checking"), 140.00, "Bad transfer did NOT fail atomically!")
 
    def testTransactionalBankWithNoAutoTransactionalObject(self):
        appContext = ApplicationContext(DatabaseTxTestAppContextWithNoAutoTransactionalObject(self.factory))
        bank = appContext.get_object("bank")
 
        bank.open("Checking")
        bank.open("Savings")

        bank.deposit(125.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 125.00)

        bank.deposit(250.00, "Savings")
        self.assertEquals(bank.balance("Savings"), 250.00)

        bank.transfer(25.00, "Savings", "Checking")
        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 150.00)

        bank.withdraw(10.00, "Checking")
        self.assertEquals(bank.balance("Checking"), 140.00)

        amount = 0.0
        try:
            amount = bank.withdraw(1000, "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass
        self.assertEquals(amount, 0.0)

        self.assertEquals(bank.balance("Savings"), 225.00)
        self.assertEquals(bank.balance("Checking"), 140.00)

        try:
            bank.transfer(200, "Checking", "Nowhere")
            self.fail("Expected a BankException!")
        except BankException:
            pass

        self.assertEquals(bank.balance("Savings"), 225.00, "Bad transfer did NOT fail atomically!")
        self.assertEquals(bank.balance("Checking"), -60.00, "Bad transfer did NOT fail as expected (not atomically due to lack of AutoTransactionalObject)")