def test_captures_output_from_completed_process(self): # Write to both stdout and stderr. proc = Popen( "echo -n foo >&1 && echo -n bar >&2", stdout=PIPE, stderr=PIPE, shell=True, ) # Wait for it to finish before capturing. self.assertEquals(0, proc.wait()) # Capturing now still gets foo and bar. self.assertThat( self.capture(proc), MatchesListwise( ( Equals(0), Equals("foo"), Equals("bar"), # The writes to stdout and stderr occur so close in time that # they may be received in any order. MatchesAny(Equals("foobar"), Equals("barfoo")), ) ), )
def test_getAllClients(self): service = RegionService(sentinel.ipcWorker) uuid1 = factory.make_UUID() c1 = DummyConnection() c2 = DummyConnection() service.connections[uuid1].update({c1, c2}) uuid2 = factory.make_UUID() c3 = DummyConnection() c4 = DummyConnection() service.connections[uuid2].update({c3, c4}) clients = service.getAllClients() self.assertThat( list(clients), MatchesAny( MatchesSetwise(Equals(RackClient(c1, {})), Equals(RackClient(c3, {}))), MatchesSetwise(Equals(RackClient(c1, {})), Equals(RackClient(c4, {}))), MatchesSetwise(Equals(RackClient(c2, {})), Equals(RackClient(c3, {}))), MatchesSetwise(Equals(RackClient(c2, {})), Equals(RackClient(c4, {}))), ), )
self.assertIsNone(security.load_region_certificate()) def test_get_region_certificate(self): cert = security.generate_region_certificate() security.save_region_certificate(cert) self.assertEqual(cert, security.get_region_certificate()) def test_get_region_certificate_when_none_exists(self): cert = security.get_region_certificate() self.assertThat(cert, is_valid_region_certificate) self.assertEqual(cert, security.load_region_certificate()) is_valid_secret = MatchesAll( IsInstance(bytes), AfterPreprocessing(len, MatchesAny(Equals(16), GreaterThan(16))), ) class TestGetSharedSecret(MAASTransactionServerTestCase): def test__generates_new_secret_when_none_exists(self): secret = security.get_shared_secret() self.assertThat(secret, is_valid_secret) def test__same_secret_is_returned_on_subsequent_calls(self): self.assertEqual( security.get_shared_secret(), security.get_shared_secret() ) def test__uses_database_secret_when_none_on_fs(self): secret_before = security.get_shared_secret()
def LessThanOrEqual(value): return MatchesAny(LessThan(value), Equals(value))
def GreaterThanOrEqual(value): return MatchesAny(GreaterThan(value), Equals(value))
def assert_time_difference(earlier_inst_index, later_inst_index): td = instances_and_visit_times[later_inst_index][1] - \ instances_and_visit_times[earlier_inst_index][1] self.assertThat(td, MatchesAny(Equals(1), GreaterThan(1)))
def test_disconnectionerror_view_integration(self): # Test setup. self.useFixture(FakeLogger('SiteError', level=logging.CRITICAL)) self.useFixture(Urllib2Fixture()) bouncer = PGBouncerFixture() # XXX gary bug=974617, bug=1011847, bug=504291 2011-07-03: # In parallel tests, we are rarely encountering instances of # bug 504291 while running this test. These cause the tests # to fail entirely (the store.rollback() described in comment # 11 does not fix the insane state) despite nultiple retries. # As mentioned in that bug, we are trying aborts to see if they # eliminate the problem. If this works, we can find which of # these two aborts are actually needed. transaction.abort() self.useFixture(bouncer) transaction.abort() # Verify things are working initially. url = 'http://launchpad.dev/' self.retryConnection(url, bouncer) # Now break the database, and we get an exception, along with # our view and several OOPSes from the retries. bouncer.stop() class Disconnects(Equals): def __init__(self, message): super(Disconnects, self).__init__( ('DisconnectionError', message)) with CaptureOops() as oopses: error = self.getHTTPError(url) self.assertEqual(503, error.code) self.assertThat(error.read(), Contains(DisconnectionErrorView.reason)) self.assertThat( [(oops['type'], oops['value'].split('\n')[0]) for oops in oopses.oopses], MatchesListwise( [MatchesAny( # libpq < 9.5. Disconnects('error with no message from the libpq'), # libpq >= 9.5. Disconnects('server closed the connection unexpectedly'))] * 2 + [Disconnects( 'could not connect to server: Connection refused')] * 6)) # We keep seeing the correct exception on subsequent requests. with CaptureOops() as oopses: error = self.getHTTPError(url) self.assertEqual(503, error.code) self.assertThat(error.read(), Contains(DisconnectionErrorView.reason)) self.assertThat( [(oops['type'], oops['value'].split('\n')[0]) for oops in oopses.oopses], MatchesListwise( [Disconnects( 'could not connect to server: Connection refused')] * 8)) # When the database is available again, requests succeed. bouncer.start() self.retryConnection(url, bouncer) # If we ask pgbouncer to disable the database, requests fail and # get the same error page, but we don't log OOPSes except for # the initial connection terminations. Disablement is always # explicit maintenance, and we don't need lots of ongoing OOPSes # to tell us about maintenance that we're doing. dbname = DatabaseLayer._db_fixture.dbname conn = psycopg2.connect("dbname=pgbouncer") conn.autocommit = True cur = conn.cursor() cur.execute("DISABLE " + dbname) cur.execute("KILL " + dbname) cur.execute("RESUME " + dbname) with CaptureOops() as oopses: error = self.getHTTPError(url) self.assertEqual(503, error.code) self.assertThat(error.read(), Contains(DisconnectionErrorView.reason)) self.assertThat( [(oops['type'], oops['value'].split('\n')[0]) for oops in oopses.oopses], MatchesListwise([Disconnects('database removed')])) # A second request doesn't log any OOPSes. with CaptureOops() as oopses: error = self.getHTTPError(url) self.assertEqual(503, error.code) self.assertThat(error.read(), Contains(DisconnectionErrorView.reason)) self.assertEqual( [], [(oops['type'], oops['value'].split('\n')[0]) for oops in oopses.oopses]) # When the database is available again, requests succeed. cur.execute("ENABLE %s" % DatabaseLayer._db_fixture.dbname) self.retryConnection(url, bouncer)
def lesser_or_equal(v): """ Matches a value less than or equal to ``v``. """ return MatchesAny(LessThan(v), Equals(v))
def greater_or_equal(v): """ Matches a value greater than or equal to ``v``. """ return MatchesAny(GreaterThan(v), Equals(v))
def Optional(matcher, default=Is(None)): return MatchesAny(matcher, default)