From f9f0ce224552130609e83a836da5eaef9be28b84 Mon Sep 17 00:00:00 2001 From: Mattie Fu Date: Tue, 20 Oct 2026 21:49:22 +0000 Subject: [PATCH] test(bigtable): add accelerator default, config, metrics, and startup system tests --- .../test_config_forwarding_async.py | 38 +++++++++++++++++ .../test_config_forwarding_autogen.py | 35 ++++++++++++++++ .../test_default_and_fallback_async.py | 39 ++++++++++++++++++ .../test_default_and_fallback_autogen.py | 35 ++++++++++++++++ .../accelerator/test_metrics_parity_async.py | 41 +++++++++++++++++++ .../test_metrics_parity_autogen.py | 38 +++++++++++++++++ .../data/accelerator/test_startup_async.py | 35 ++++++++++++++++ .../data/accelerator/test_startup_autogen.py | 32 +++++++++++++++ 8 files changed, 293 insertions(+) create mode 100644 packages/google-cloud-bigtable/tests/system/data/accelerator/test_config_forwarding_async.py create mode 100644 packages/google-cloud-bigtable/tests/system/data/accelerator/test_config_forwarding_autogen.py create mode 100644 packages/google-cloud-bigtable/tests/system/data/accelerator/test_default_and_fallback_async.py create mode 100644 packages/google-cloud-bigtable/tests/system/data/accelerator/test_default_and_fallback_autogen.py create mode 100644 packages/google-cloud-bigtable/tests/system/data/accelerator/test_metrics_parity_async.py create mode 100644 packages/google-cloud-bigtable/tests/system/data/accelerator/test_metrics_parity_autogen.py create mode 100644 packages/google-cloud-bigtable/tests/system/data/accelerator/test_startup_async.py create mode 100644 packages/google-cloud-bigtable/tests/system/data/accelerator/test_startup_autogen.py diff --git a/packages/google-cloud-bigtable/tests/system/data/accelerator/test_config_forwarding_async.py b/packages/google-cloud-bigtable/tests/system/data/accelerator/test_config_forwarding_async.py new file mode 100644 index 000000000000..1c578239d470 --- /dev/null +++ b/packages/google-cloud-bigtable/tests/system/data/accelerator/test_config_forwarding_async.py @@ -0,0 +1,38 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import os +import uuid +from google.cloud.bigtable.data._cross_sync import CrossSync +from google.cloud.bigtable.data.mutations import DeleteAllFromRow, SetCell +from . import _harness +if CrossSync.is_async: + from ._base_async import AcceleratorTestBaseAsync as AcceleratorTestBase +else: + from ._base_autogen import AcceleratorTestBase +__CROSS_SYNC_OUTPUT__ = "tests.system.data.accelerator.test_config_forwarding_autogen" + + +@CrossSync.convert_class(sync_name="TestConfigForwarding") +class TestConfigForwardingAsync(AcceleratorTestBase): + @CrossSync.pytest + async def test_app_profile_forwarded_to_daemon(self, instance_id, table_id): + ep = os.environ.get("BIGTABLE_EMULATOR_HOST") or "bigtable.googleapis.com:443" + async with self._make_client(use_accelerator=True, client_options={"api_endpoint": ep, "quota_project_id": "test-quota-proj"}) as client, client.get_table(instance_id, table_id, app_profile_id="test-profile") as table: + assert table._accelerator_client is not None and _harness.pid_alive(_harness.daemon_pid(table)) + f = table._accelerator_daemon._cli_flags + assert (f[f.index("--app-profile") + 1], f[f.index("--instance") + 1], f[f.index("--data-endpoint") + 1], f[f.index("--quota-project") + 1]) == ("test-profile", instance_id, ep.split("://")[-1], "test-quota-proj") + key = f"cfg-{uuid.uuid4().hex}".encode() + await table.mutate_row(key, SetCell(_harness.TEST_FAMILY, b"q", b"v", 1000 * _harness.MS)) + assert (await table.read_row(key)) is not None + await table.mutate_row(key, DeleteAllFromRow()) diff --git a/packages/google-cloud-bigtable/tests/system/data/accelerator/test_config_forwarding_autogen.py b/packages/google-cloud-bigtable/tests/system/data/accelerator/test_config_forwarding_autogen.py new file mode 100644 index 000000000000..22f6034395d2 --- /dev/null +++ b/packages/google-cloud-bigtable/tests/system/data/accelerator/test_config_forwarding_autogen.py @@ -0,0 +1,35 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file is automatically generated by CrossSync. Do not edit manually. + +import os +import uuid +from google.cloud.bigtable.data._cross_sync import CrossSync +from google.cloud.bigtable.data.mutations import DeleteAllFromRow, SetCell +from . import _harness +from ._base_autogen import AcceleratorTestBase + +class TestConfigForwarding(AcceleratorTestBase): + + def test_app_profile_forwarded_to_daemon(self, instance_id, table_id): + ep = os.environ.get('BIGTABLE_EMULATOR_HOST') or 'bigtable.googleapis.com:443' + with self._make_client(use_accelerator=True, client_options={'api_endpoint': ep, 'quota_project_id': 'test-quota-proj'}) as client, client.get_table(instance_id, table_id, app_profile_id='test-profile') as table: + assert table._accelerator_client is not None and _harness.pid_alive(_harness.daemon_pid(table)) + f = table._accelerator_daemon._cli_flags + assert (f[f.index('--app-profile') + 1], f[f.index('--instance') + 1], f[f.index('--data-endpoint') + 1], f[f.index('--quota-project') + 1]) == ('test-profile', instance_id, ep.split('://')[-1], 'test-quota-proj') + key = f'cfg-{uuid.uuid4().hex}'.encode() + table.mutate_row(key, SetCell(_harness.TEST_FAMILY, b'q', b'v', 1000 * _harness.MS)) + assert table.read_row(key) is not None + table.mutate_row(key, DeleteAllFromRow()) \ No newline at end of file diff --git a/packages/google-cloud-bigtable/tests/system/data/accelerator/test_default_and_fallback_async.py b/packages/google-cloud-bigtable/tests/system/data/accelerator/test_default_and_fallback_async.py new file mode 100644 index 000000000000..7a7f697fe988 --- /dev/null +++ b/packages/google-cloud-bigtable/tests/system/data/accelerator/test_default_and_fallback_async.py @@ -0,0 +1,39 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import uuid +from google.cloud.bigtable.data._cross_sync import CrossSync +from google.cloud.bigtable.data.mutations import SetCell +from . import _harness +if CrossSync.is_async: + from ._base_async import AcceleratorTestBaseAsync as AcceleratorTestBase +else: + from ._base_autogen import AcceleratorTestBase +__CROSS_SYNC_OUTPUT__ = "tests.system.data.accelerator.test_default_and_fallback_autogen" + + +@CrossSync.convert_class(sync_name="TestDefaultAndFallback") +class TestDefaultAndFallbackAsync(AcceleratorTestBase): + @CrossSync.pytest + async def test_default_enables_accelerator(self, default_table, janitor): + assert default_table._accelerator_client is not None + key = janitor.track(f"contract-{uuid.uuid4().hex}".encode()) + await default_table.mutate_row(key, SetCell(_harness.TEST_FAMILY, b"q", b"v", 1000 * _harness.MS)) + assert (await default_table.read_row(key)).cells[0].value == b"v" + + @CrossSync.pytest + async def test_explicit_false_uses_native(self, native_table, janitor): + assert native_table._accelerator_client is None and native_table._accelerator_daemon is None + key = janitor.track(f"contract-{uuid.uuid4().hex}".encode()) + await native_table.mutate_row(key, SetCell(_harness.TEST_FAMILY, b"q", b"v", 1000 * _harness.MS)) + assert (await native_table.read_row(key)).cells[0].value == b"v" diff --git a/packages/google-cloud-bigtable/tests/system/data/accelerator/test_default_and_fallback_autogen.py b/packages/google-cloud-bigtable/tests/system/data/accelerator/test_default_and_fallback_autogen.py new file mode 100644 index 000000000000..dbe17e1938f1 --- /dev/null +++ b/packages/google-cloud-bigtable/tests/system/data/accelerator/test_default_and_fallback_autogen.py @@ -0,0 +1,35 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file is automatically generated by CrossSync. Do not edit manually. + +import uuid +from google.cloud.bigtable.data._cross_sync import CrossSync +from google.cloud.bigtable.data.mutations import SetCell +from . import _harness +from ._base_autogen import AcceleratorTestBase + +class TestDefaultAndFallback(AcceleratorTestBase): + + def test_default_enables_accelerator(self, default_table, janitor): + assert default_table._accelerator_client is not None + key = janitor.track(f'contract-{uuid.uuid4().hex}'.encode()) + default_table.mutate_row(key, SetCell(_harness.TEST_FAMILY, b'q', b'v', 1000 * _harness.MS)) + assert default_table.read_row(key).cells[0].value == b'v' + + def test_explicit_false_uses_native(self, native_table, janitor): + assert native_table._accelerator_client is None and native_table._accelerator_daemon is None + key = janitor.track(f'contract-{uuid.uuid4().hex}'.encode()) + native_table.mutate_row(key, SetCell(_harness.TEST_FAMILY, b'q', b'v', 1000 * _harness.MS)) + assert native_table.read_row(key).cells[0].value == b'v' \ No newline at end of file diff --git a/packages/google-cloud-bigtable/tests/system/data/accelerator/test_metrics_parity_async.py b/packages/google-cloud-bigtable/tests/system/data/accelerator/test_metrics_parity_async.py new file mode 100644 index 000000000000..7a25f1bce1e1 --- /dev/null +++ b/packages/google-cloud-bigtable/tests/system/data/accelerator/test_metrics_parity_async.py @@ -0,0 +1,41 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import uuid +from google.cloud.bigtable.data._cross_sync import CrossSync +from google.cloud.bigtable.data._metrics.handlers._base import MetricsHandler +from google.cloud.bigtable.data.mutations import DeleteAllFromRow, SetCell +from . import _harness +if CrossSync.is_async: + from ._base_async import AcceleratorTestBaseAsync as AcceleratorTestBase +else: + from ._base_autogen import AcceleratorTestBase +__CROSS_SYNC_OUTPUT__ = "tests.system.data.accelerator.test_metrics_parity_autogen" + + +@CrossSync.convert_class(sync_name="TestMetricsParity") +class TestMetricsParityAsync(AcceleratorTestBase): + @CrossSync.pytest + async def test_accelerated_ops_bypass_python_metrics(self, instance_id, table_id): + ah, nh, a_ops, n_ops = MetricsHandler(), MetricsHandler(), [], [] + ah.on_operation_complete, nh.on_operation_complete = a_ops.append, n_ops.append + async with self._make_client(use_accelerator=True) as ac, self._make_client(use_accelerator=False) as nc, ac.get_table(instance_id, table_id) as accel_table, nc.get_table(instance_id, table_id) as native_table: + assert accel_table._accelerator_client is not None and native_table._accelerator_client is None + accel_table.client._metrics.add_handler(ah) + native_table.client._metrics.add_handler(nh) + key = f"metrics-{uuid.uuid4().hex}".encode() + for t in (accel_table, native_table): + await t.mutate_row(key, SetCell(_harness.TEST_FAMILY, b"q", b"v", 1000 * _harness.MS)) + await t.read_row(key) + await t.mutate_row(key, DeleteAllFromRow()) + assert len(n_ops) >= 2 and len(a_ops) == 0 diff --git a/packages/google-cloud-bigtable/tests/system/data/accelerator/test_metrics_parity_autogen.py b/packages/google-cloud-bigtable/tests/system/data/accelerator/test_metrics_parity_autogen.py new file mode 100644 index 000000000000..1342c0397c26 --- /dev/null +++ b/packages/google-cloud-bigtable/tests/system/data/accelerator/test_metrics_parity_autogen.py @@ -0,0 +1,38 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file is automatically generated by CrossSync. Do not edit manually. + +import uuid +from google.cloud.bigtable.data._cross_sync import CrossSync +from google.cloud.bigtable.data._metrics.handlers._base import MetricsHandler +from google.cloud.bigtable.data.mutations import DeleteAllFromRow, SetCell +from . import _harness +from ._base_autogen import AcceleratorTestBase + +class TestMetricsParity(AcceleratorTestBase): + + def test_accelerated_ops_bypass_python_metrics(self, instance_id, table_id): + ah, nh, a_ops, n_ops = (MetricsHandler(), MetricsHandler(), [], []) + ah.on_operation_complete, nh.on_operation_complete = (a_ops.append, n_ops.append) + with self._make_client(use_accelerator=True) as ac, self._make_client(use_accelerator=False) as nc, ac.get_table(instance_id, table_id) as accel_table, nc.get_table(instance_id, table_id) as native_table: + assert accel_table._accelerator_client is not None and native_table._accelerator_client is None + accel_table.client._metrics.add_handler(ah) + native_table.client._metrics.add_handler(nh) + key = f'metrics-{uuid.uuid4().hex}'.encode() + for t in (accel_table, native_table): + t.mutate_row(key, SetCell(_harness.TEST_FAMILY, b'q', b'v', 1000 * _harness.MS)) + t.read_row(key) + t.mutate_row(key, DeleteAllFromRow()) + assert len(n_ops) >= 2 and len(a_ops) == 0 \ No newline at end of file diff --git a/packages/google-cloud-bigtable/tests/system/data/accelerator/test_startup_async.py b/packages/google-cloud-bigtable/tests/system/data/accelerator/test_startup_async.py new file mode 100644 index 000000000000..8b1395e28b92 --- /dev/null +++ b/packages/google-cloud-bigtable/tests/system/data/accelerator/test_startup_async.py @@ -0,0 +1,35 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import time +import pytest +from google.cloud.bigtable.data._cross_sync import CrossSync +from . import _harness +if CrossSync.is_async: + from ._base_async import AcceleratorTestBaseAsync as AcceleratorTestBase +else: + from ._base_autogen import AcceleratorTestBase +__CROSS_SYNC_OUTPUT__ = "tests.system.data.accelerator.test_startup_autogen" + + +@CrossSync.convert_class(sync_name="TestStartup") +class TestStartupAsync(AcceleratorTestBase): + @CrossSync.pytest + async def test_slow_bind_waits_then_falls_back(self, tmp_bin_dir, instance_id, table_id, monkeypatch): + _harness.slow_bind_binary(tmp_bin_dir, 1.5, monkeypatch=monkeypatch) + t0 = time.monotonic() + async with self._make_client() as client: + with pytest.warns(RuntimeWarning): + table = client.get_table(instance_id, table_id) + async with table: + assert time.monotonic() - t0 >= 0.75 and table._accelerator_client is None diff --git a/packages/google-cloud-bigtable/tests/system/data/accelerator/test_startup_autogen.py b/packages/google-cloud-bigtable/tests/system/data/accelerator/test_startup_autogen.py new file mode 100644 index 000000000000..17ac27bdef49 --- /dev/null +++ b/packages/google-cloud-bigtable/tests/system/data/accelerator/test_startup_autogen.py @@ -0,0 +1,32 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file is automatically generated by CrossSync. Do not edit manually. + +import time +import pytest +from google.cloud.bigtable.data._cross_sync import CrossSync +from . import _harness +from ._base_autogen import AcceleratorTestBase + +class TestStartup(AcceleratorTestBase): + + def test_slow_bind_waits_then_falls_back(self, tmp_bin_dir, instance_id, table_id, monkeypatch): + _harness.slow_bind_binary(tmp_bin_dir, 1.5, monkeypatch=monkeypatch) + t0 = time.monotonic() + with self._make_client() as client: + with pytest.warns(RuntimeWarning): + table = client.get_table(instance_id, table_id) + with table: + assert time.monotonic() - t0 >= 0.75 and table._accelerator_client is None \ No newline at end of file