Example #1
0
def test_run_circuit_failed_missing_processor_name(client):
    client().create_program.return_value = (
        'prog',
        quantum.QuantumProgram(name='projects/proj/programs/prog'),
    )
    client().create_job.return_value = (
        'job-id',
        quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job-id',
                           execution_status={'state': 'READY'}),
    )
    client().get_job.return_value = quantum.QuantumJob(
        name='projects/proj/programs/prog/jobs/job-id',
        execution_status={
            'state': 'FAILURE',
            'failure': {
                'error_code': 'SYSTEM_ERROR',
                'error_message': 'Not good'
            },
        },
    )

    engine = cg.Engine(project_id='proj')
    with pytest.raises(
            RuntimeError,
            match='Job projects/proj/programs/prog/jobs/job-id on processor'
            ' UNKNOWN failed. SYSTEM_ERROR: Not good',
    ):
        engine.run(program=_CIRCUIT)
def test_sampler(client):
    client().create_program.return_value = (
        'prog',
        quantum.QuantumProgram(name='projects/proj/programs/prog'),
    )
    client().create_job.return_value = (
        'job-id',
        quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job-id',
                           execution_status={'state': 'READY'}),
    )
    client().get_job.return_value = quantum.QuantumJob(
        execution_status={'state': 'SUCCESS'},
        update_time=_to_timestamp('2019-07-09T23:39:59Z'))
    client().get_job_results.return_value = quantum.QuantumResult(
        result=util.pack_any(_RESULTS_V2))
    processor = cg.EngineProcessor('proj', 'mysim', EngineContext())
    sampler = processor.get_sampler()
    results = sampler.run_sweep(
        program=_CIRCUIT,
        params=[cirq.ParamResolver({'a': 1}),
                cirq.ParamResolver({'a': 2})])
    assert len(results) == 2
    for i, v in enumerate([1, 2]):
        assert results[i].repetitions == 1
        assert results[i].params.param_dict == {'a': v}
        assert results[i].measurements == {'q': np.array([[0]], dtype='uint8')}
    assert client().create_program.call_args[0][0] == 'proj'
def test_set_job_description(client_constructor):
    grpc_client = setup_mock_(client_constructor)

    result = quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job0')
    grpc_client.update_quantum_job.return_value = result

    client = EngineClient()
    assert client.set_job_description('proj', 'prog', 'job0', 'A job') == result
    grpc_client.update_quantum_job.assert_called_with(
        quantum.UpdateQuantumJobRequest(
            name='projects/proj/programs/prog/jobs/job0',
            quantum_job=quantum.QuantumJob(
                name='projects/proj/programs/prog/jobs/job0', description='A job'
            ),
            update_mask=FieldMask(paths=['description']),
        )
    )

    assert client.set_job_description('proj', 'prog', 'job0', '') == result
    grpc_client.update_quantum_job.assert_called_with(
        quantum.UpdateQuantumJobRequest(
            name='projects/proj/programs/prog/jobs/job0',
            quantum_job=quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job0'),
            update_mask=FieldMask(paths=['description']),
        )
    )
def test_set_job_labels(client_constructor):
    grpc_client = setup_mock_(client_constructor)

    grpc_client.get_quantum_job.return_value = quantum.QuantumJob(
        labels={'color': 'red', 'weather': 'sun', 'run': '1'}, label_fingerprint='hash'
    )
    result = quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job0')
    grpc_client.update_quantum_job.return_value = result

    client = EngineClient()
    labels = {'hello': 'world', 'color': 'blue', 'run': '1'}
    assert client.set_job_labels('proj', 'prog', 'job0', labels) == result
    grpc_client.update_quantum_job.assert_called_with(
        quantum.UpdateQuantumJobRequest(
            name='projects/proj/programs/prog/jobs/job0',
            quantum_job=quantum.QuantumJob(
                name='projects/proj/programs/prog/jobs/job0',
                labels=labels,
                label_fingerprint='hash',
            ),
            update_mask=FieldMask(paths=['labels']),
        )
    )

    assert client.set_job_labels('proj', 'prog', 'job0', {}) == result
    grpc_client.update_quantum_job.assert_called_with(
        quantum.UpdateQuantumJobRequest(
            name='projects/proj/programs/prog/jobs/job0',
            quantum_job=quantum.QuantumJob(
                name='projects/proj/programs/prog/jobs/job0', label_fingerprint='hash'
            ),
            update_mask=FieldMask(paths=['labels']),
        )
    )
Example #5
0
def test_run_batch_delegation(create_job):
    create_job.return_value = ('kittens', quantum.QuantumJob())
    program = cg.EngineProgram('my-meow', 'my-meow', EngineContext(), result_type=ResultType.Batch)
    resolver_list = [cirq.Points('cats', [1.0, 2.0, 3.0]), cirq.Points('cats', [4.0, 5.0, 6.0])]
    job = program.run_batch(
        job_id='steve', repetitions=10, params_list=resolver_list, processor_ids=['lazykitty']
    )
    assert job._job == quantum.QuantumJob()
Example #6
0
def test_run_sweeps_delegation(create_job):
    create_job.return_value = ('steve', quantum.QuantumJob())
    program = cg.EngineProgram('my-proj', 'my-prog', EngineContext())
    param_resolver = cirq.ParamResolver({})
    job = program.run_sweep(
        job_id='steve', repetitions=10, params=param_resolver, processor_ids=['mine']
    )
    assert job._job == quantum.QuantumJob()
Example #7
0
def test_set_description(set_job_description):
    job = cg.EngineJob('a', 'b', 'steve', EngineContext())
    set_job_description.return_value = quantum.QuantumJob(description='world')
    assert job.set_description('world').description() == 'world'
    set_job_description.assert_called_with('a', 'b', 'steve', 'world')

    set_job_description.return_value = quantum.QuantumJob(description='')
    assert job.set_description('').description() == ''
    set_job_description.assert_called_with('a', 'b', 'steve', '')
Example #8
0
def test_description(get_job):
    job = cg.EngineJob('a',
                       'b',
                       'steve',
                       EngineContext(),
                       _job=quantum.QuantumJob(description='hello'))
    assert job.description() == 'hello'
    get_job.return_value = quantum.QuantumJob(description='hello')
    assert cg.EngineJob('a', 'b', 'steve',
                        EngineContext()).description() == 'hello'
    get_job.assert_called_once_with('a', 'b', 'steve', False)
Example #9
0
def setup_run_circuit_with_result_(client, result):
    client().create_program.return_value = (
        'prog',
        quantum.QuantumProgram(name='projects/proj/programs/prog'),
    )
    client().create_job.return_value = (
        'job-id',
        quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job-id',
                           execution_status={'state': 'READY'}),
    )
    client().get_job.return_value = quantum.QuantumJob(
        execution_status={'state': 'SUCCESS'}, update_time=_DT)
    client().get_job_results.return_value = quantum.QuantumResult(
        result=result)
Example #10
0
def test_get_repetitions_and_sweeps_v1(get_job):
    job = cg.EngineJob('a', 'b', 'steve', EngineContext())
    get_job.return_value = quantum.QuantumJob(run_context=util.pack_any(
        v1.program_pb2.RunContext(
            parameter_sweeps=[v1.params_pb2.ParameterSweep(repetitions=10)])))
    with pytest.raises(ValueError, match='v1 RunContext is not supported'):
        job.get_repetitions_and_sweeps()
Example #11
0
    async def create_job_async(
        self,
        project_id: str,
        program_id: str,
        job_id: Optional[str],
        processor_ids: Sequence[str],
        run_context: any_pb2.Any,
        priority: Optional[int] = None,
        description: Optional[str] = None,
        labels: Optional[Dict[str, str]] = None,
    ) -> Tuple[str, quantum.QuantumJob]:
        """Creates and runs a job on Quantum Engine.

        Args:
            project_id: A project_id of the parent Google Cloud Project.
            program_id: Unique ID of the program within the parent project.
            job_id: Unique ID of the job within the parent program.
            run_context: Properly serialized run context.
            processor_ids: List of processor id for running the program.
            priority: Optional priority to run at, 0-1000.
            description: Optional description to set on the job.
            labels: Optional set of labels to set on the job.

        Returns:
            Tuple of created job id and job.

        Raises:
            ValueError: If the priority is not betwen 0 and 1000.
        """
        # Check program to run and program parameters.
        if priority and not 0 <= priority < 1000:
            raise ValueError('priority must be between 0 and 1000')

        # Create job.
        job_name = _job_name_from_ids(project_id, program_id, job_id) if job_id else ''
        job = quantum.QuantumJob(
            name=job_name,
            scheduling_config=quantum.SchedulingConfig(
                processor_selector=quantum.SchedulingConfig.ProcessorSelector(
                    processor_names=[
                        _processor_name_from_ids(project_id, processor_id)
                        for processor_id in processor_ids
                    ]
                )
            ),
            run_context=run_context,
        )
        if priority:
            job.scheduling_config.priority = priority
        if description:
            job.description = description
        if labels:
            job.labels.update(labels)
        request = quantum.CreateQuantumJobRequest(
            parent=_program_name_from_ids(project_id, program_id),
            quantum_job=job,
            overwrite_existing_run_context=False,
        )
        job = await self._send_request_async(self.grpc_client.create_quantum_job, request)
        return _ids_from_job_name(job.name)[2], job
Example #12
0
def test_labels():
    job = cg.EngineJob('a',
                       'b',
                       'steve',
                       EngineContext(),
                       _job=quantum.QuantumJob(labels={'t': '1'}))
    assert job.labels() == {'t': '1'}
Example #13
0
def test_run_batch_no_sweeps(create_job):
    # Running with no sweeps is fine. Uses program's batch size to create
    # proper empty sweeps.
    create_job.return_value = ('kittens', quantum.QuantumJob())
    program = cg.EngineProgram(
        'my-meow',
        'my-meow',
        _program=quantum.QuantumProgram(code=_BATCH_PROGRAM_V2),
        context=EngineContext(),
        result_type=ResultType.Batch,
    )
    job = program.run_batch(job_id='steve', repetitions=10, processor_ids=['lazykitty'])
    assert job._job == quantum.QuantumJob()
    batch_run_context = v2.batch_pb2.BatchRunContext()
    create_job.call_args[1]['run_context'].Unpack(batch_run_context)
    assert len(batch_run_context.run_contexts) == 1
Example #14
0
def test_batched_results(get_job_results):
    qjob = quantum.QuantumJob(
        execution_status=quantum.ExecutionStatus(
            state=quantum.ExecutionStatus.State.SUCCESS),
        update_time=UPDATE_TIME,
    )
    get_job_results.return_value = BATCH_RESULTS

    job = cg.EngineJob('a', 'b', 'steve', EngineContext(), _job=qjob)
    data = job.results()
    assert len(data) == 4
    assert str(data[0]) == 'q=011'
    assert str(data[1]) == 'q=111'
    assert str(data[2]) == 'q=1101'
    assert str(data[3]) == 'q=1001'
    get_job_results.assert_called_once_with('a', 'b', 'steve')

    data = job.batched_results()
    assert len(data) == 2
    assert len(data[0]) == 2
    assert len(data[1]) == 2
    assert str(data[0][0]) == 'q=011'
    assert str(data[0][1]) == 'q=111'
    assert str(data[1][0]) == 'q=1101'
    assert str(data[1][1]) == 'q=1001'
Example #15
0
def test_get_calibration(get_calibration):
    qjob = quantum.QuantumJob(execution_status=quantum.ExecutionStatus(
        calibration_name='projects/a/processors/p/calibrations/123'))
    calibration = quantum.QuantumCalibration(data=util.pack_any(
        Merge(
            """
    timestamp_ms: 123000,
    metrics: [{
        name: 'xeb',
        targets: ['0_0', '0_1'],
        values: [{
            double_val: .9999
        }]
    }, {
        name: 't1',
        targets: ['0_0'],
        values: [{
            double_val: 321
        }]
    }, {
        name: 'globalMetric',
        values: [{
            int32_val: 12300
        }]
    }]
""",
            v2.metrics_pb2.MetricsSnapshot(),
        )))
    get_calibration.return_value = calibration

    job = cg.EngineJob('a', 'b', 'steve', EngineContext(), _job=qjob)
    assert list(job.get_calibration()) == ['xeb', 't1', 'globalMetric']
    get_calibration.assert_called_once_with('a', 'p', 123)
Example #16
0
def test_get_repetitions_and_sweeps_unsupported(get_job):
    job = cg.EngineJob('a', 'b', 'steve', EngineContext())
    get_job.return_value = quantum.QuantumJob(run_context=any_pb2.Any(
        type_url='type.googleapis.com/unknown.proto'))
    with pytest.raises(ValueError,
                       match='unsupported run_context type: unknown.proto'):
        job.get_repetitions_and_sweeps()
Example #17
0
def test_get_repetitions_and_sweeps(get_job):
    job = cg.EngineJob('a', 'b', 'steve', EngineContext())
    get_job.return_value = quantum.QuantumJob(run_context=util.pack_any(
        v2.run_context_pb2.RunContext(parameter_sweeps=[
            v2.run_context_pb2.ParameterSweep(repetitions=10)
        ])))
    assert job.get_repetitions_and_sweeps() == (10, [cirq.UnitSweep])
    get_job.assert_called_once_with('a', 'b', 'steve', True)
def test_run_batch(client):
    client().create_program.return_value = (
        'prog',
        quantum.QuantumProgram(name='projects/proj/programs/prog'),
    )
    client().create_job.return_value = (
        'job-id',
        quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job-id',
                           execution_status={'state': 'READY'}),
    )
    client().get_job.return_value = quantum.QuantumJob(
        execution_status={'state': 'SUCCESS'},
        update_time=_to_timestamp('2019-07-09T23:39:59Z'))
    client().get_job_results.return_value = quantum.QuantumResult(
        result=_BATCH_RESULTS_V2)

    processor = cg.EngineProcessor('a', 'p', EngineContext())
    job = processor.run_batch(
        programs=[_CIRCUIT, _CIRCUIT],
        job_id='job-id',
        params_list=[cirq.Points('a', [1, 2]),
                     cirq.Points('a', [3, 4])],
    )
    results = job.results()
    assert len(results) == 4
    for i, v in enumerate([1, 2, 3, 4]):
        assert results[i].repetitions == 1
        assert results[i].params.param_dict == {'a': v}
        assert results[i].measurements == {'q': np.array([[0]], dtype='uint8')}
    for result in results:
        assert result.job_id == job.id()
    client().create_program.assert_called_once()
    client().create_job.assert_called_once()
    run_context = v2.batch_pb2.BatchRunContext()
    client().create_job.call_args[1]['run_context'].Unpack(run_context)
    assert len(run_context.run_contexts) == 2
    for idx, rc in enumerate(run_context.run_contexts):
        sweeps = rc.parameter_sweeps
        assert len(sweeps) == 1
        assert sweeps[0].repetitions == 1
        if idx == 0:
            assert sweeps[0].sweep.single_sweep.points.points == [1.0, 2.0]
        if idx == 1:
            assert sweeps[0].sweep.single_sweep.points.points == [3.0, 4.0]
    client().get_job.assert_called_once()
    client().get_job_results.assert_called_once()
Example #19
0
def test_run_circuit_timeout(client):
    client().create_program_async.return_value = (
        'prog',
        quantum.QuantumProgram(name='projects/proj/programs/prog'),
    )
    client().create_job_async.return_value = (
        'job-id',
        quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job-id',
                           execution_status={'state': 'READY'}),
    )
    client().get_job_async.return_value = quantum.QuantumJob(
        name='projects/proj/programs/prog/jobs/job-id',
        execution_status={'state': 'RUNNING'})

    engine = cg.Engine(project_id='project-id', timeout=1)
    with pytest.raises(TimeoutError):
        engine.run(program=_CIRCUIT)
Example #20
0
def test_run_circuit_timeout(patched_time_sleep, client):
    client().create_program.return_value = (
        'prog',
        quantum.QuantumProgram(name='projects/proj/programs/prog'),
    )
    client().create_job.return_value = (
        'job-id',
        quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job-id',
                           execution_status={'state': 'READY'}),
    )
    client().get_job.return_value = quantum.QuantumJob(
        name='projects/proj/programs/prog/jobs/job-id',
        execution_status={'state': 'RUNNING'})

    engine = cg.Engine(project_id='project-id', timeout=600)
    with pytest.raises(RuntimeError, match='Timed out'):
        engine.run(program=_CIRCUIT)
def test_run_sweep_params(client):
    client().create_program.return_value = (
        'prog',
        quantum.QuantumProgram(name='projects/proj/programs/prog'),
    )
    client().create_job.return_value = (
        'job-id',
        quantum.QuantumJob(name='projects/proj/programs/prog/jobs/job-id',
                           execution_status={'state': 'READY'}),
    )
    client().get_job.return_value = quantum.QuantumJob(
        execution_status={'state': 'SUCCESS'},
        update_time=_to_timestamp('2019-07-09T23:39:59Z'))
    client().get_job_results.return_value = quantum.QuantumResult(
        result=util.pack_any(_RESULTS_V2))

    processor = cg.EngineProcessor('a', 'p', EngineContext())
    job = processor.run_sweep(
        program=_CIRCUIT,
        params=[cirq.ParamResolver({'a': 1}),
                cirq.ParamResolver({'a': 2})])
    results = job.results()
    assert len(results) == 2
    for i, v in enumerate([1, 2]):
        assert results[i].repetitions == 1
        assert results[i].params.param_dict == {'a': v}
        assert results[i].measurements == {'q': np.array([[0]], dtype='uint8')}
    for result in results:
        assert result.job_id == job.id()
        assert result.job_finished_time is not None
    assert results == cirq.read_json(json_text=cirq.to_json(results))

    client().create_program.assert_called_once()
    client().create_job.assert_called_once()

    run_context = v2.run_context_pb2.RunContext()
    client().create_job.call_args[1]['run_context'].Unpack(run_context)
    sweeps = run_context.parameter_sweeps
    assert len(sweeps) == 2
    for i, v in enumerate([1.0, 2.0]):
        assert sweeps[i].repetitions == 1
        assert sweeps[i].sweep.sweep_function.sweeps[
            0].single_sweep.points.points == [v]
    client().get_job.assert_called_once()
    client().get_job_results.assert_called_once()
Example #22
0
def test_run_calibration(client):
    client().create_program_async.return_value = (
        'prog',
        quantum.QuantumProgram(name='projects/proj/programs/prog'),
    )
    client().create_job_async.return_value = (
        'job-id',
        quantum.QuantumJob(
            name='projects/proj/programs/prog/jobs/job-id', execution_status={'state': 'READY'}
        ),
    )
    client().get_job_async.return_value = quantum.QuantumJob(execution_status={'state': 'SUCCESS'})
    client().get_job_results_async.return_value = quantum.QuantumResult(
        result=_CALIBRATION_RESULTS_V2
    )

    q1 = cirq.GridQubit(2, 3)
    q2 = cirq.GridQubit(2, 4)
    layer1 = cg.CalibrationLayer('xeb', cirq.Circuit(cirq.CZ(q1, q2)), {'num_layers': 42})
    layer2 = cg.CalibrationLayer(
        'readout', cirq.Circuit(cirq.measure(q1, q2)), {'num_samples': 4242}
    )
    processor = cg.EngineProcessor('proj', 'mysim', EngineContext())
    job = processor.run_calibration(layers=[layer1, layer2], job_id='job-id')
    results = job.calibration_results()
    assert len(results) == 2
    assert results[0].code == v2.calibration_pb2.SUCCESS
    assert results[0].error_message == 'First success'
    assert results[0].token == 'abc123'
    assert len(results[0].metrics) == 1
    assert len(results[0].metrics['fidelity']) == 1
    assert results[0].metrics['fidelity'][(q1, q2)] == [0.75]
    assert results[1].code == v2.calibration_pb2.SUCCESS
    assert results[1].error_message == 'Second success'

    # assert label is correct
    client().create_job_async.assert_called_once_with(
        project_id='proj',
        program_id='prog',
        job_id='job-id',
        processor_ids=['mysim'],
        run_context=util.pack_any(v2.run_context_pb2.RunContext()),
        description=None,
        labels={'calibration': ''},
    )
Example #23
0
def test_set_labels(set_job_labels):
    job = cg.EngineJob('a', 'b', 'steve', EngineContext())
    set_job_labels.return_value = quantum.QuantumJob(labels={
        'a': '1',
        'b': '1'
    })
    assert job.set_labels({
        'a': '1',
        'b': '1'
    }).labels() == {
        'a': '1',
        'b': '1'
    }
    set_job_labels.assert_called_with('a', 'b', 'steve', {'a': '1', 'b': '1'})

    set_job_labels.return_value = quantum.QuantumJob()
    assert job.set_labels({}).labels() == {}
    set_job_labels.assert_called_with('a', 'b', 'steve', {})
Example #24
0
def test_remove_labels(remove_job_labels):
    job = cg.EngineJob('a',
                       'b',
                       'steve',
                       EngineContext(),
                       _job=quantum.QuantumJob(labels={
                           'a': '1',
                           'b': '1'
                       }))
    assert job.labels() == {'a': '1', 'b': '1'}

    remove_job_labels.return_value = quantum.QuantumJob(labels={'b': '1'})
    assert job.remove_labels(['a']).labels() == {'b': '1'}
    remove_job_labels.assert_called_with('a', 'b', 'steve', ['a'])

    remove_job_labels.return_value = quantum.QuantumJob(labels={})
    assert job.remove_labels(['a', 'b', 'c']).labels() == {}
    remove_job_labels.assert_called_with('a', 'b', 'steve', ['a', 'b', 'c'])
Example #25
0
def test_status(get_job):
    qjob = quantum.QuantumJob(execution_status=quantum.ExecutionStatus(
        state=quantum.ExecutionStatus.State.RUNNING))
    get_job.return_value = qjob

    job = cg.EngineJob('a', 'b', 'steve', EngineContext())
    assert job.status() == 'RUNNING'
    get_job.assert_called_once()
    assert job.execution_status() == quantum.ExecutionStatus.State.RUNNING
Example #26
0
def test_list_jobs(list_jobs):
    job1 = quantum.QuantumJob(name='projects/proj/programs/prog1/jobs/job1')
    job2 = quantum.QuantumJob(name='projects/otherproj/programs/prog1/jobs/job2')
    list_jobs.return_value = [job1, job2]

    ctx = EngineContext()
    result = cg.EngineProgram(project_id='proj', program_id='prog1', context=ctx).list_jobs()
    list_jobs.assert_called_once_with(
        'proj',
        'prog1',
        created_after=None,
        created_before=None,
        has_labels=None,
        execution_states=None,
    )
    assert [(j.program_id, j.project_id, j.job_id, j.context, j._job) for j in result] == [
        ('prog1', 'proj', 'job1', ctx, job1),
        ('prog1', 'otherproj', 'job2', ctx, job2),
    ]
Example #27
0
def test_calibration_results_not_a_calibration(get_job_results):
    qjob = quantum.QuantumJob(
        execution_status=quantum.ExecutionStatus(
            state=quantum.ExecutionStatus.State.SUCCESS),
        update_time=UPDATE_TIME,
    )
    get_job_results.return_value = RESULTS
    job = cg.EngineJob('a', 'b', 'steve', EngineContext(), _job=qjob)
    with pytest.raises(ValueError, match='calibration results'):
        job.calibration_results()
Example #28
0
def test_results_len(get_job_results):
    qjob = quantum.QuantumJob(
        execution_status=quantum.ExecutionStatus(
            state=quantum.ExecutionStatus.State.SUCCESS),
        update_time=UPDATE_TIME,
    )
    get_job_results.return_value = RESULTS

    job = cg.EngineJob('a', 'b', 'steve', EngineContext(), _job=qjob)
    assert len(job) == 2
Example #29
0
def test_timeout(get_job):
    qjob = quantum.QuantumJob(
        execution_status=quantum.ExecutionStatus(
            state=quantum.ExecutionStatus.State.RUNNING),
        update_time=UPDATE_TIME,
    )
    get_job.return_value = qjob
    job = cg.EngineJob('a', 'b', 'steve', EngineContext(timeout=0.1))
    with pytest.raises(TimeoutError):
        job.results()
def test_list_jobs(client_constructor):
    grpc_client = setup_mock_(client_constructor)

    results = [
        quantum.QuantumJob(name='projects/proj/programs/prog1/jobs/job1'),
        quantum.QuantumJob(name='projects/proj/programs/prog1/jobs/job2'),
    ]
    grpc_client.list_quantum_jobs.return_value = results

    client = EngineClient()
    assert client.list_jobs(project_id='proj', program_id='prog1') == results
    grpc_client.list_quantum_jobs.assert_called_with(
        quantum.ListQuantumJobsRequest(parent='projects/proj/programs/prog1')
    )

    assert client.list_jobs(project_id='proj') == results
    grpc_client.list_quantum_jobs.assert_called_with(
        quantum.ListQuantumJobsRequest(parent='projects/proj/programs/-')
    )