diff --git a/google/cloud/bigquery/job.py b/google/cloud/bigquery/job.py index 678c1ddc0dae..85418ad3a3c8 100644 --- a/google/cloud/bigquery/job.py +++ b/google/cloud/bigquery/job.py @@ -375,7 +375,7 @@ def cancel(self, client=None): api_response = client.connection.api_request( method='POST', path='%s/cancel' % (self.path,)) - self._set_properties(api_response) + self._set_properties(api_response['job']) class _LoadConfiguration(object): diff --git a/system_tests/bigquery.py b/system_tests/bigquery.py index fbb3921d4a41..d48bd146105a 100644 --- a/system_tests/bigquery.py +++ b/system_tests/bigquery.py @@ -432,3 +432,37 @@ def _job_done(instance): by_age = operator.itemgetter(1) self.assertEqual(sorted(rows, key=by_age), sorted(ROWS, key=by_age)) + + def test_job_cancel(self): + DATASET_NAME = _make_dataset_name('job_cancel') + JOB_NAME = 'fetch_' + DATASET_NAME + TABLE_NAME = 'test_table' + QUERY = 'SELECT * FROM %s.%s' % (DATASET_NAME, TABLE_NAME) + + dataset = Config.CLIENT.dataset(DATASET_NAME) + + retry_403(dataset.create)() + self.to_delete.append(dataset) + + full_name = bigquery.SchemaField('full_name', 'STRING', + mode='REQUIRED') + age = bigquery.SchemaField('age', 'INTEGER', mode='REQUIRED') + table = dataset.table(TABLE_NAME, schema=[full_name, age]) + table.create() + self.to_delete.insert(0, table) + + job = Config.CLIENT.run_async_query(JOB_NAME, QUERY) + job.begin() + job.cancel() + + def _job_done(instance): + return instance.state in ('DONE', 'done') + + retry = RetryInstanceState(_job_done, max_tries=8) + retry(job.reload)() + + # The `cancel` API doesn't leave any reliable traces on + # the status of the job resource, so we can't really assert for + # them here. The best we can do is not that the API call didn't + # raise an error, and that the job completed (in the `retry()` + # above). diff --git a/unit_tests/bigquery/test_job.py b/unit_tests/bigquery/test_job.py index 1808196177d3..09ea4dbc2731 100644 --- a/unit_tests/bigquery/test_job.py +++ b/unit_tests/bigquery/test_job.py @@ -601,8 +601,9 @@ def test_reload_w_alternate_client(self): def test_cancel_w_bound_client(self): PATH = 'projects/%s/jobs/%s/cancel' % (self.PROJECT, self.JOB_NAME) - RESOURCE = self._makeResource() - conn = _Connection(RESOURCE) + RESOURCE = self._makeResource(ended=True) + RESPONSE = {'job': RESOURCE} + conn = _Connection(RESPONSE) client = _Client(project=self.PROJECT, connection=conn) table = _Table() job = self._makeOne(self.JOB_NAME, table, [self.SOURCE1], client) @@ -617,10 +618,11 @@ def test_cancel_w_bound_client(self): def test_cancel_w_alternate_client(self): PATH = 'projects/%s/jobs/%s/cancel' % (self.PROJECT, self.JOB_NAME) - RESOURCE = self._makeResource() + RESOURCE = self._makeResource(ended=True) + RESPONSE = {'job': RESOURCE} conn1 = _Connection() client1 = _Client(project=self.PROJECT, connection=conn1) - conn2 = _Connection(RESOURCE) + conn2 = _Connection(RESPONSE) client2 = _Client(project=self.PROJECT, connection=conn2) table = _Table() job = self._makeOne(self.JOB_NAME, table, [self.SOURCE1], client1)