Ejemplo n.º 1
0
    def test_submit_ok_reply(self):
        """Handle a normal query and response."""
        with Client('endpoint', 'token') as client:
            client.session = mock.Mock()
            client.session.post = lambda a, _: choose_reply(
                a, {
                    'endpoint/problems/':
                    '[%s]' % complete_no_answer_reply('123', 'abc123')
                })
            client.session.get = lambda a: choose_reply(
                a, {'endpoint/problems/123/': complete_reply('123', 'abc123')})
            solver = Solver(client, solver_data('abc123'))

            # Build a problem
            linear = {index: 1 for index in solver.nodes}
            quad = {key: -1 for key in solver.undirected_edges}
            results = solver.sample_ising(linear, quad, num_reads=100)

            self._check(results, linear, quad, 100)
    def test_submit_null_reply(self):
        """Get an error when the server's response is incomplete."""

        # 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/': ''})
            return session

        with mock.patch.object(Client, 'create_session', create_mock_session):
            with Client('endpoint', 'token') as client:
                solver = Solver(client, solver_data('abc123'))

                linear, quadratic = test_problem(solver)
                results = solver.sample_ising(linear, quadratic)

                with self.assertRaises(InvalidAPIResponseError):
                    results.samples
    def test_cancel_without_id(self):
        """Make sure the cancel method submits to the right endpoint.

        When cancel is called before the submission has returned the problem id.
        """
        submission_id = 'test-id'
        reply_body = '[%s]' % continue_reply(submission_id, 'solver')

        release_reply = threading.Event()

        with Client('endpoint', 'token') as client:
            client.session = mock.Mock()
            client.session.get = lambda a: choose_reply(
                a,
                {'endpoint/problems/?id={}'.format(submission_id): reply_body})

            def post(a, _):
                release_reply.wait()
                return choose_reply(a, {'endpoint/problems/': reply_body})

            client.session.post = post
            client.session.delete = DeleteEvent.handle

            solver = Solver(client, solver_data('abc123'))
            # Build a problem
            linear = {index: 1 for index in solver.nodes}
            quad = {key: -1 for key in solver.undirected_edges}
            future = solver.sample_ising(linear, quad)
            future.cancel()

            try:
                release_reply.set()
                future.samples
                self.fail()
            except DeleteEvent as event:
                if event.url == 'endpoint/problems/':
                    self.assertEqual(event.body,
                                     '["{}"]'.format(submission_id))
                else:
                    self.assertEqual(
                        event.url,
                        'endpoint/problems/{}/'.format(submission_id))
Ejemplo n.º 4
0
    def test_submit_cancel_reply(self):
        """Handle a response for a canceled job."""

        # 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/': '[%s]' % cancel_reply('123', 'abc123')})
            return session

        with mock.patch.object(Client, 'create_session', create_mock_session):
            with Client('endpoint', 'token') as client:
                solver = Solver(client, solver_data('abc123'))

                linear, quadratic = test_problem(solver)
                results = solver.sample_ising(linear, quadratic, num_reads=100)

                with self.assertRaises(CanceledFutureError):
                    results.samples
    def test_submit_immediate_error_reply(self):
        """Handle an (obvious) error on problem submission."""

        # 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/': '[%s]' % immediate_error_reply(
                    400, "Missing parameter 'num_reads' in problem JSON")})
            return session

        with mock.patch.object(Client, 'create_session', create_mock_session):
            with Client('endpoint', 'token') as client:
                solver = Solver(client, solver_data('abc123'))

                linear, quadratic = test_problem(solver)
                results = solver.sample_ising(linear, quadratic)

                with self.assertRaises(SolverFailureError):
                    results.samples
    def test_submit_offset_wrong_offset_in_answer(self):
        """Energy levels don't match because offset in answer is respected, even if wrong"""

        # ising problem energy offset
        offset = 3
        answer_offset = 2 * offset  # make it wrong

        # 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/':
                '[%s]' % complete_no_answer_reply('123', 'abc123')
            })
            session.get = lambda a: choose_reply(
                a, {
                    'problems/123/':
                    complete_reply(
                        '123', 'abc123', answer=dict(offset=answer_offset))
                })
            return session

        with mock.patch.object(Client, 'create_session', create_mock_session):
            with Client('endpoint', 'token') as client:
                solver = Solver(client, solver_data('abc123'))

                linear, quadratic = test_problem(solver)
                params = dict(num_reads=100)
                results = solver.sample_ising(linear, quadratic, offset,
                                              **params)

                # since SAPI response includes offset, Future shouldn't patch it;
                # but because the offset in answer is wrong, energies are off
                with self.assertRaises(AssertionError):
                    self._check(results,
                                linear,
                                quadratic,
                                offset=offset,
                                **params)
Ejemplo n.º 7
0
    def test_id_integration(self):
        """Problem ID getter blocks correctly when ID set by the client."""

        submission_id = 'test-id'
        solver_name = 'solver-id'
        release_reply = threading.Event()

        # each thread can have its instance of a session because
        # we use a global lock (event) in the mocked responses
        def create_mock_session(client):
            session = mock.Mock()

            # delayed submit; emulates waiting in queue
            def post(path, _):
                release_reply.wait()
                reply_body = complete_reply(submission_id, solver_name)
                return choose_reply(path, {'problems/': '[%s]' % reply_body})

            session.post = post

            return session

        with mock.patch.object(Client, 'create_session', create_mock_session):
            with Client('endpoint', 'token') as client:
                solver = Solver(client, solver_data(solver_name))

                linear, quadratic = test_problem(solver)

                future = solver.sample_ising(linear, quadratic)

                # initially, the id is not available
                with self.assertRaises(TimeoutError):
                    future.wait_id(timeout=1)

                # release the mocked sapi reply with the id
                release_reply.set()

                # verify the id is now available
                self.assertEqual(future.wait_id(), submission_id)
    def test_submit_continue_then_ok_reply(self):
        """Handle polling for a complete problem."""

        now = datetime_in_future(0)
        eta_min, eta_max = datetime_in_future(10), datetime_in_future(30)

        # 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/':
                '[%s]' % continue_reply(
                    '123', 'abc123', eta_min=eta_min, eta_max=eta_max, now=now)
            },
                                                     date=now)
            session.get = lambda a: choose_reply(a, {
                'problems/?id=123':
                '[%s]' % complete_no_answer_reply('123', 'abc123'),
                'problems/123/':
                complete_reply('123', 'abc123')
            },
                                                 date=now)
            return session

        with mock.patch.object(Client, 'create_session', create_mock_session):
            with Client('endpoint', 'token') as client:
                solver = Solver(client, solver_data('abc123'))

                linear, quadratic = test_problem(solver)
                params = dict(num_reads=100)
                results = solver.sample_ising(linear, quadratic, **params)

                self._check(results, linear, quadratic, **params)

                # test future has eta_min and eta_max parsed correctly
                self.assertEqual(results.eta_min, eta_min)
                self.assertEqual(results.eta_max, eta_max)
Ejemplo n.º 9
0
    def test_submit_ok_reply(self):
        """Handle a normal query and response."""

        # 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/':
                '[%s]' % complete_no_answer_reply('123', 'abc123')
            })
            session.get = lambda a: choose_reply(
                a, {'problems/123/': complete_reply('123', 'abc123')})
            return session

        with mock.patch.object(Client, 'create_session', create_mock_session):
            with Client('endpoint', 'token') as client:
                solver = Solver(client, solver_data('abc123'))

                linear, quadratic = test_problem(solver)
                results = solver.sample_ising(linear, quadratic, num_reads=100)

                self._check(results, linear, quadratic, 100)
    def test_submit_continue_then_error_reply(self):
        """Handle polling for an error message."""
        with Client('endpoint', 'token') as client:
            client.session = mock.Mock()
            client.session.post = lambda a, _: choose_reply(
                a, {
                    'endpoint/problems/': '[%s]' % continue_reply(
                        '123', 'abc123')
                })
            client.session.get = lambda a: choose_reply(
                a, {
                    'endpoint/problems/?id=123':
                    '[%s]' % error_reply('123', 'abc123', "error message")
                })
            solver = Solver(client, solver_data('abc123'))

            # Build a problem
            linear = {index: 1 for index in solver.nodes}
            quad = {key: -1 for key in solver.undirected_edges}
            results = solver.sample_ising(linear, quad, num_reads=100)

            with self.assertRaises(SolverFailureError):
                self._check(results, linear, quad, 100)
Ejemplo n.º 11
0
    def test_submit_continue_then_ok_and_error_reply(self):
        """Handle polling for the status of multiple problems."""

        # we need a "global session", because mocked responses are stateful
        def global_mock_session():
            session = mock.Mock()

            # on first status poll, return pending for both problems
            # on second status poll, return error for first problem and complete for second
            def continue_then_complete(path, state={'count': 0}):
                state['count'] += 1
                if state['count'] < 2:
                    return choose_reply(
                        path, {
                            'problems/?id=1':
                            '[{}]'.format(continue_reply('1', 'abc123')),
                            'problems/?id=2':
                            '[{}]'.format(continue_reply('2', 'abc123')),
                            'problems/1/':
                            continue_reply('1', 'abc123'),
                            'problems/2/':
                            continue_reply('2', 'abc123'),
                            'problems/?id=1,2':
                            '[{},{}]'.format(continue_reply('1', 'abc123'),
                                             continue_reply('2', 'abc123')),
                            'problems/?id=2,1':
                            '[{},{}]'.format(continue_reply('2', 'abc123'),
                                             continue_reply('1', 'abc123'))
                        })
                else:
                    return choose_reply(
                        path, {
                            'problems/?id=1':
                            '[{}]'.format(error_reply('1', 'abc123', 'error')),
                            'problems/?id=2':
                            '[{}]'.format(
                                complete_no_answer_reply('2', 'abc123')),
                            'problems/1/':
                            error_reply('1', 'abc123', 'error'),
                            'problems/2/':
                            complete_reply('2', 'abc123'),
                            'problems/?id=1,2':
                            '[{},{}]'.format(
                                error_reply('1', 'abc123', 'error'),
                                complete_no_answer_reply('2', 'abc123')),
                            'problems/?id=2,1':
                            '[{},{}]'.format(
                                complete_no_answer_reply('2', 'abc123'),
                                error_reply('1', 'abc123', 'error'))
                        })

            def accept_problems_with_continue_reply(path, body,
                                                    ids=iter('12')):
                problems = json.loads(body)
                return choose_reply(
                    path, {
                        'problems/':
                        json.dumps([
                            json.loads(continue_reply(next(ids), 'abc123'))
                            for _ in problems
                        ])
                    })

            session.get = continue_then_complete
            session.post = accept_problems_with_continue_reply

            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, solver_data('abc123'))

                linear, quadratic = test_problem(solver)

                results1 = solver.sample_ising(linear,
                                               quadratic,
                                               num_reads=100)
                results2 = solver.sample_ising(linear,
                                               quadratic,
                                               num_reads=100)

                with self.assertRaises(SolverFailureError):
                    self._check(results1, linear, quadratic, 100)
                self._check(results2, linear, quadratic, 100)
    def test_submit_continue_then_ok_and_error_reply(self):
        """Handle polling for the status of multiple problems."""

        with Client('endpoint', 'token') as client:
            client.session = mock.Mock()

            # on first status poll, return pending for both problems
            # on second status poll, return error for first problem and complete for second
            def continue_then_complete(path, state={'count': 0}):
                state['count'] += 1
                if state['count'] < 2:
                    return choose_reply(
                        path, {
                            'endpoint/problems/?id=1':
                            '[{}]'.format(continue_reply('1', 'abc123')),
                            'endpoint/problems/?id=2':
                            '[{}]'.format(continue_reply('2', 'abc123')),
                            'endpoint/problems/1/':
                            continue_reply('1', 'abc123'),
                            'endpoint/problems/2/':
                            continue_reply('2', 'abc123'),
                            'endpoint/problems/?id=1,2':
                            '[{},{}]'.format(continue_reply('1', 'abc123'),
                                             continue_reply('2', 'abc123')),
                            'endpoint/problems/?id=2,1':
                            '[{},{}]'.format(continue_reply('2', 'abc123'),
                                             continue_reply('1', 'abc123'))
                        })
                else:
                    return choose_reply(
                        path, {
                            'endpoint/problems/?id=1':
                            '[{}]'.format(error_reply('1', 'abc123', 'error')),
                            'endpoint/problems/?id=2':
                            '[{}]'.format(
                                complete_no_answer_reply('2', 'abc123')),
                            'endpoint/problems/1/':
                            error_reply('1', 'abc123', 'error'),
                            'endpoint/problems/2/':
                            complete_reply('2', 'abc123'),
                            'endpoint/problems/?id=1,2':
                            '[{},{}]'.format(
                                error_reply('1', 'abc123', 'error'),
                                complete_no_answer_reply('2', 'abc123')),
                            'endpoint/problems/?id=2,1':
                            '[{},{}]'.format(
                                complete_no_answer_reply('2', 'abc123'),
                                error_reply('1', 'abc123', 'error'))
                        })

            client.session.get = continue_then_complete

            def accept_problems_with_continue_reply(path, body,
                                                    ids=iter('12')):
                problems = json.loads(body)
                return choose_reply(
                    path, {
                        'endpoint/problems/':
                        json.dumps([
                            json.loads(continue_reply(next(ids), 'abc123'))
                            for _ in problems
                        ])
                    })

            client.session.post = accept_problems_with_continue_reply

            solver = Solver(client, solver_data('abc123'))

            linear = {index: 1 for index in solver.nodes}
            quad = {key: -1 for key in solver.undirected_edges}

            results1 = solver.sample_ising(linear, quad, num_reads=100)
            results2 = solver.sample_ising(linear, quad, num_reads=100)

            with self.assertRaises(SolverFailureError):
                self._check(results1, linear, quad, 100)
            self._check(results2, linear, quad, 100)