def childStore(self): """ Create a store suitable for use in a child process, that is hooked up to the store that a parent test process is managing. """ disableMemcacheForTest(TestCase()) staticQuota = 3000 attachmentRoot = (FilePath(self.sharedDBPath).child("attachments")) stubsvc = self.createService(lambda cf: Service()) cp = ConnectionPool( stubsvc.produceConnection, maxConnections=1, dbtype=DatabaseType(DB_TYPE[0], DB_TYPE[1]), ) # Attach the service to the running reactor. cp.startService() reactor.addSystemEventTrigger("before", "shutdown", cp.stopService) cds = CommonDataStore(cp.connection, { "push": StubNotifierFactory(), }, None, attachmentRoot, "", quota=staticQuota) return cds
class SteppablePoolHelper(ConnectionPoolHelper): """ A version of L{ConnectionPoolHelper} that can set up a connection pool capable of firing all its L{Deferred}s on demand, synchronously, by using SQLite. """ dbtype = DatabaseType(SQLITE_DIALECT, sqlite3.paramstyle) def __init__(self, schema): self.schema = schema def setUp(self, test): connect = synchronousConnectionFactory(test) con = connect() cur = con.cursor() cur.executescript(self.schema) con.commit() super(SteppablePoolHelper, self).setUp(test, connect) def rows(self, sql): """ Get some rows from the database to compare in a test. """ con = self.connect() cur = con.cursor() cur.execute(sql) result = cur.fetchall() con.commit() return result
def _staticSQL(sql, doquote=False): """ Statically generate some SQL from some DAL syntax objects, interpolating any parameters into the body of the string. @note: Do not use this function with untrusted input, as it may be a security risk. This is only for translating local, trusted input from the schema. @param sql: something from L{twext.enterprise.dal}, either a top-level statement like L{Insert} or L{Select}, or a fragment such as an expression. @param doquote: Force all identifiers to be double-quoted, whether they conflict with database identifiers or not, for consistency. @return: the generated SQL string. @rtype: C{str} """ qgen = QueryGenerator(DatabaseType(ORACLE_DIALECT, "pyformat"), FixedPlaceholder('%s')) if doquote: qgen.shouldQuote = lambda name: True if hasattr(sql, 'subSQL'): fragment = sql.subSQL(qgen, []) else: fragment = sql.toSQL(qgen) params = tuple([_quoted(param) for param in fragment.parameters]) result = fragment.text % params return result
def buildConnectionPool(testCase, schemaText="", dbtype=DatabaseType(SQLITE_DIALECT, "numeric")): """ Build a L{ConnectionPool} for testing purposes, with the given C{testCase}. @param testCase: the test case to attach the resulting L{ConnectionPool} to. @type testCase: L{twisted.trial.unittest.TestCase} @param schemaText: The text of the schema with which to initialize the database. @type schemaText: L{str} @return: a L{ConnectionPool} service whose C{startService} method has already been invoked. @rtype: L{ConnectionPool} """ sqlitename = testCase.mktemp() seqs = {} def connectionFactory(label=testCase.id()): conn = sqlite3.connect(sqlitename, isolation_level=None) def nextval(seq): result = seqs[seq] = seqs.get(seq, 0) + 1 return result conn.create_function("nextval", 1, nextval) return conn con = connectionFactory() con.executescript(schemaText) con.commit() pool = ConnectionPool(connectionFactory, dbtype=dbtype) pool.startService() testCase.addCleanup(pool.stopService) return pool
def makeAndCleanStore(self, testCase, notifierFactory, directoryService, attachmentRoot, enableJobProcessing=True): """ Create a L{CommonDataStore} specific to the given L{TestCase}. This also creates a L{ConnectionPool} that gets stopped when the test finishes, to make sure that any test which fails will terminate cleanly. @return: a L{Deferred} that fires with a L{CommonDataStore} """ # Always clean-out old attachments if attachmentRoot.exists(): attachmentRoot.remove() attachmentRoot.createDirectory() currentTestID = testCase.id() cp = ConnectionPool( self.sharedService.produceConnection, maxConnections=4, dbtype=DatabaseType(DB_TYPE[0], DB_TYPE[1]), ) quota = deriveQuota(testCase) store = CommonDataStore( cp.connection, {"push": notifierFactory} if notifierFactory is not None else {}, directoryService, attachmentRoot, "https://example.com/calendars/__uids__/%(home)s/dropbox/%(dropbox_id)s/%(name)s", quota=quota) store.label = currentTestID cp.startService() @inlineCallbacks def stopIt(): if enableJobProcessing: txn = store.newTransaction() jobs = yield JobItem.all(txn) yield txn.commit() yield pool.stopService() else: jobs = () # active transactions should have been shut down. wasBusy = len(cp._busy) busyText = repr(cp._busy) result = yield cp.stopService() if deriveValue(testCase, _SPECIAL_TXN_CLEAN, lambda tc: False): if wasBusy: testCase.fail("Outstanding Transactions: " + busyText) returnValue(result) if len(jobs): testCase.fail("Jobs left in job queue {}: {}".format( testCase, ",".join([job.workType for job in jobs]))) returnValue(result) testCase.addCleanup(stopIt) yield self.cleanStore(testCase, store) # Start the job queue after store is up and cleaned if enableJobProcessing: pool = ControllerQueue(reactor, store.newTransaction, useWorkerPool=False) store.queuer = store.pool = pool pool.startService() returnValue(store)
class ConnectionPoolHelper(object): """ Connection pool setting-up facilities for tests that need a L{ConnectionPool}. """ dbtype = DatabaseType(POSTGRES_DIALECT, DEFAULT_PARAM_STYLE) def setUp(self, test=None, connect=None): """ Support inheritance by L{TestCase} classes. """ if test is None: test = self if connect is None: self.factory = ConnectionFactory() connect = self.factory.connect self.connect = connect self.paused = False self.holders = [] self.pool = ConnectionPool( connect, maxConnections=2, dbtype=self.dbtype, ) self.pool._createHolder = self.makeAHolder self.clock = self.pool.reactor = ClockWithThreads() self.pool.startService() test.addCleanup(self.flushHolders) def flushHolders(self): """ Flush all pending C{submit}s since C{pauseHolders} was called. This makes sure the service is stopped and the fake ThreadHolders are all executing their queues so failed tests can exit cleanly. """ self.paused = False for holder in self.holders: holder.flush() def pauseHolders(self): """ Pause all L{FakeThreadHolder}s, causing C{submit} to return an unfired L{Deferred}. """ self.paused = True def makeAHolder(self): """ Make a ThreadHolder-alike. """ fth = FakeThreadHolder(self) self.holders.append(fth) return fth def resultOf(self, it): return resultOf(it) def createTransaction(self): return self.pool.connection() def translateError(self, err): return err