def test_immediate_polling_with_local_clock_unsynced(self): """First poll happens with minimal delay if local clock is way off from the remote/server clock.""" # each thread can have its instance of a session because # the mocked responses are stateless def create_mock_session(client): badnow = utcrel(100) session = mock.Mock() session.post = lambda path, _: choose_reply( path, {'problems/': [self.sapi.continue_reply(id='1')]}, date=badnow) session.get = lambda path: choose_reply(path, { 'problems/?id=1': [self.sapi.complete_no_answer_reply(id='1')], 'problems/1/': self.sapi.complete_reply(id='1') }, date=badnow) return session with mock.patch.object(Client, 'create_session', create_mock_session): with Client('endpoint', 'token') as client: solver = Solver(client, self.sapi.solver.data) def assert_no_delay(s): s and self.assertTrue( abs(s - client.poll_backoff_min) < client.DEFAULTS['poll_backoff_min']) with mock.patch('time.sleep', assert_no_delay): future = solver.sample_qubo({}) future.result()
def test_immediate_polling(self): "First poll happens with minimal delay" # each thread can have its instance of a session because # responses are stateless def create_mock_session(client): session = mock.Mock() session.post = lambda path, _: choose_reply( path, {'problems/': [self.sapi.continue_reply(id='1')]}) session.get = lambda path: choose_reply( path, { 'problems/?id=1': [self.sapi.complete_no_answer_reply(id='1')], 'problems/1/': self.sapi.complete_reply(id='1') }) return session with mock.patch.object(Client, 'create_session', create_mock_session): with Client(endpoint='endpoint', token='token') as client: solver = Solver(client, self.sapi.solver.data) def assert_no_delay(s): s and self.assertTrue( abs(s - client.poll_backoff_min) < client.DEFAULTS['poll_backoff_min']) with mock.patch('time.sleep', assert_no_delay): future = solver.sample_qubo({}) future.result()
def test_polling_recovery_after_5xx(self): "Polling shouldn't be aborted on 5xx responses." # we need a "global session", because mocked responses are stateful def global_mock_session(): session = mock.Mock() # on submit, return status pending session.post = lambda path, _: choose_reply( path, {'problems/': [self.sapi.continue_reply(id='123')]}) # on first and second status poll, fail with 503 and 504 # on third status poll, return completed statuses = iter([503, 504]) def continue_then_complete(path, state={'count': 0}): state['count'] += 1 if state['count'] < 3: return choose_reply( path, replies={ 'problems/?id=123': [self.sapi.continue_reply(id='123')], 'problems/123/': self.sapi.continue_reply(id='123') }, statuses={ 'problems/?id=123': statuses, 'problems/123/': statuses }) else: return choose_reply( path, { 'problems/?id=123': [self.sapi.complete_no_answer_reply(id='123')], 'problems/123/': self.sapi.complete_reply(id='123') }) session.get = continue_then_complete return session session = global_mock_session() with mock.patch.object(Client, 'create_session', lambda self: session): with Client(endpoint='endpoint', token='token') as client: solver = Solver(client, self.sapi.solver.data) future = solver.sample_qubo({}) future.result() # after third poll, back-off interval should be 4 x initial back-off self.assertAlmostEqual( future._poll_backoff, client.poll_backoff_min * client.poll_backoff_base**2)
def test_exponential_backoff_polling(self): "After each poll, back-off should double" # we need a "global session", because mocked responses are stateful def global_mock_session(): session = mock.Mock() # on submit, return status pending session.post = lambda path, _: choose_reply( path, {'problems/': [self.sapi.continue_reply(id='123')]}) # on first and second status poll, return pending # on third status poll, return completed def continue_then_complete(path, state={'count': 0}): state['count'] += 1 if state['count'] < 3: return choose_reply( path, { 'problems/?id=123': [self.sapi.continue_reply(id='123')], 'problems/123/': self.sapi.continue_reply(id='123') }) else: return choose_reply( path, { 'problems/?id=123': [self.sapi.complete_no_answer_reply(id='123')], 'problems/123/': self.sapi.complete_reply(id='123') }) session.get = continue_then_complete return session session = global_mock_session() with mock.patch.object(Client, 'create_session', lambda self: session): with Client('endpoint', 'token') as client: solver = Solver(client, self.sapi.solver.data) future = solver.sample_qubo({}) future.result() # after third poll, back-off interval should be 4 x initial back-off self.assertEqual(future._poll_backoff, client.poll_backoff_min * 2**2)
def test_submit_bqm_qubo_ok_reply(self): """Handle a normal query and response.""" qubo_msg_diff = dict(type="qubo") qubo_answer_diff = { 'energies': 'AAAAAAAAAAA=', 'solutions': 'AA==', 'active_variables': 'AAAAAAQAAAA=' } # each thread can have its instance of a session because # the mocked responses are stateless def create_mock_session(client): session = mock.Mock() session.post = lambda a, _: choose_reply(a, { 'problems/': [self.sapi.complete_no_answer_reply(id='123')] }) session.get = lambda a: choose_reply( a, { 'problems/123/': self.sapi.complete_reply(id='123', answer_patch=qubo_answer_diff, **qubo_msg_diff) }) return session with mock.patch.object(Client, 'create_session', create_mock_session): with Client('endpoint', 'token') as client: solver = Solver(client, self.sapi.solver.data) qubo = {(0, 0): 4.0, (0, 4): -4, (4, 4): 4.0} offset = -2.0 params = dict(num_reads=100) results = solver.sample_qubo(qubo, offset, **params) # make sure energies are correct in raw results for energy, sample in zip(results.energies, results.samples): self.assertEqual( energy, evaluate_ising({}, qubo, sample, offset=offset))