示例#1
0
    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
示例#2
0
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
示例#3
0
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
示例#4
0
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
示例#5
0
    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)
示例#6
0
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