diff --git a/.github/workflows/conformance-tests-bigtable-emulator.yaml b/.github/workflows/conformance-tests-bigtable-emulator.yaml
new file mode 100644
index 000000000000..53d549b280e5
--- /dev/null
+++ b/.github/workflows/conformance-tests-bigtable-emulator.yaml
@@ -0,0 +1,58 @@
+# Copyright 2025 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.
+# Github action job to test core java library features on
+# downstream client libraries before they are released.
+on:
+ push:
+ branches:
+ - main
+ paths:
+ - 'Bigtable/**'
+ - '.github/workflows/conformance-tests-bigtable-emulator.yaml'
+ pull_request:
+ paths:
+ - 'Bigtable/**'
+ - '.github/workflows/conformance-tests-bigtable-emulator.yaml'
+ workflow_dispatch:
+name: Run Bigtable Conformance Tests With Emulator
+jobs:
+ conformance:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '8.1'
+ extensions: grpc
+
+ - name: Checkout Bigtable conformance tests
+ uses: actions/checkout@v4
+ with:
+ repository: googleapis/cloud-bigtable-clients-test
+ ref: main
+ path: cloud-bigtable-clients-test
+
+ - uses: actions/setup-go@v5
+ with:
+ go-version: '>=1.20.2'
+
+ - name: Install Road Runner PHP
+ run: |
+ wget https://github.com/roadrunner-server/roadrunner/releases/download/v2024.3.1/roadrunner-2024.3.1-linux-amd64.deb
+ sudo dpkg -i roadrunner-2024.3.1-linux-amd64.deb
+
+ - run: bash Bigtable/tests/Conformance/proxy/conformance.sh
diff --git a/.github/workflows/conformance-tests-storage-emulator.yaml b/.github/workflows/conformance-tests-storage-emulator.yaml
index 71405d39e36c..9ee8560c7fad 100644
--- a/.github/workflows/conformance-tests-storage-emulator.yaml
+++ b/.github/workflows/conformance-tests-storage-emulator.yaml
@@ -4,11 +4,11 @@ on:
- main
paths:
- 'Storage/**'
- - '.github/workflows/emulator-conformance-tests-storage.yaml'
+ - '.github/workflows/conformance-tests-storage-emulator.yaml'
pull_request:
paths:
- 'Storage/**'
- - '.github/workflows/emulator-conformance-tests-storage.yaml'
+ - '.github/workflows/conformance-tests-storage-emulator.yaml'
name: Run Storage Retry Conformance Tests With Emulator
jobs:
test:
diff --git a/Bigtable/src/ResumableStream.php b/Bigtable/src/ResumableStream.php
index d85597347eb4..b9e16de9214e 100644
--- a/Bigtable/src/ResumableStream.php
+++ b/Bigtable/src/ResumableStream.php
@@ -163,6 +163,7 @@ public function readAll()
$headers['bigtable-attempt'] = [(string) $totalAttempt];
($this->delayFunction)($currentAttempt);
}
+
$stream = call_user_func_array(
[$this->gapicClient, $this->method],
[$this->request, ['headers' => $headers] + $this->callOptions]
diff --git a/Bigtable/src/Table.php b/Bigtable/src/Table.php
index cbf0097c3d7f..a059d27d1687 100644
--- a/Bigtable/src/Table.php
+++ b/Bigtable/src/Table.php
@@ -573,7 +573,8 @@ private function mutateRowsWithEntries(array $entries, array $options = [])
$rowMutationsFailedResponse[] = [
'rowKey' => $entries[$mutateRowsResponseEntry->getIndex()]->getRowKey(),
'statusCode' => $mutateRowsResponseEntry->getStatus()->getCode(),
- 'message' => $mutateRowsResponseEntry->getStatus()->getMessage()
+ 'message' => $mutateRowsResponseEntry->getStatus()->getMessage(),
+ 'index' => $mutateRowsResponseEntry->getIndex(),
];
} else {
unset($entries[$mutateRowsResponseEntry->getIndex()]);
diff --git a/Bigtable/tests/Conformance/proxy/.rr.yaml b/Bigtable/tests/Conformance/proxy/.rr.yaml
new file mode 100644
index 000000000000..f311762433c5
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/.rr.yaml
@@ -0,0 +1,30 @@
+version: "3"
+rpc:
+ listen: "tcp://127.0.0.1:6001"
+
+server:
+ command: "php worker.php"
+ relay: "pipes"
+ relay_timeout: "20s"
+
+kv:
+ memory-cache:
+ driver: memory
+ config: { }
+
+grpc:
+ listen: "tcp://127.0.0.1:9999"
+ proto: ["test_proxy.proto"]
+ max_send_msg_size: 50
+ max_recv_msg_size: 50
+ max_connection_idle: 0s
+ max_connection_age: 0s
+ max_connection_age_grace: 0s
+ max_concurrent_streams: 10
+ ping_time: 1s
+ timeout: 200s
+ pool:
+ num_workers: 5
+ max_jobs: 0
+ allocate_timeout: 60s
+ destroy_timeout: 60s
diff --git a/Bigtable/tests/Conformance/proxy/composer.json b/Bigtable/tests/Conformance/proxy/composer.json
new file mode 100644
index 000000000000..ae4051467cf9
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/composer.json
@@ -0,0 +1,24 @@
+{
+ "name": "google-testing/proxy-bigtable-server",
+ "description": "Proxy Bigtable Server",
+ "repositories": [
+ {
+ "type": "path",
+ "url": "../../.."
+ }
+ ],
+ "require": {
+ "google/cloud-bigtable": "*",
+ "grpc/grpc": "^1.36",
+ "spiral/roadrunner-cli": "^2.6",
+ "spiral/roadrunner-grpc": "^3.4",
+ "spiral/roadrunner-kv": "^4.3"
+ },
+ "autoload": {
+ "psr-4": {
+ "": "src"
+ }
+ },
+ "minimum-stability": "dev",
+ "prefer-stable": true
+}
diff --git a/Bigtable/tests/Conformance/proxy/conformance.sh b/Bigtable/tests/Conformance/proxy/conformance.sh
new file mode 100644
index 000000000000..cc6f8bf216e6
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/conformance.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# Copyright 2025 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.
+
+set -eo pipefail
+
+## Get the directory of the build script
+proxyDir=$(realpath $(dirname "${BASH_SOURCE[0]}"))
+projectDir=$(realpath $proxyDir/../../../..)
+
+# Install composer dependencies in the "proxy" directory
+composer update -d $proxyDir
+
+set +e
+
+# declare -a configs=("default" "enable_all")
+declare -a configs=("default") # PHP only supports "default" feature flags for now
+for config in "${configs[@]}"
+do
+ # Start the proxy in a separate process
+ rr serve -w $proxyDir &
+ proxyPID=$!
+
+ pushd .
+ cd $projectDir/cloud-bigtable-clients-test/tests
+
+ skipTests=$(sed -n 'H;${x;s/\n/\\|/g;s/^\\|//;p;};d' < $proxyDir/known_failures.txt)
+ eval "go test -v -proxy_addr=:9999 -skip ${skipTests}"
+ returnCode=$?
+ popd
+
+ # Stop the proxy
+ kill ${proxyPID}
+
+ if [[ ${returnCode} -gt 0 ]]
+ then
+ echo "Conformance test failed for config: ${config}"
+ RETURN_CODE=${returnCode}
+ else
+ echo "Conformance test passed for config: ${config}"
+ fi
+done
+
+exit ${RETURN_CODE}
diff --git a/Bigtable/tests/Conformance/proxy/known_failures.txt b/Bigtable/tests/Conformance/proxy/known_failures.txt
new file mode 100644
index 000000000000..5b227f9d9f26
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/known_failures.txt
@@ -0,0 +1,10 @@
+_Retry_WithRoutingCookie
+_Retry_WithRetryInfo
+TestMutateRows_Generic_DeadlineExceeded
+TestReadRow_Generic_DeadlineExceeded
+TestReadRows_NoRetry_OutOfOrderError
+TestReadRows_Retry_StreamReset
+TestReadRows_Retry_PausedScan
+TestReadRows_Retry_LastScannedRow
+TestReadRows_ReverseScans_FeatureFlag_Enabled
+TestReadRows_Generic_DeadlineExceeded
diff --git a/Bigtable/tests/Conformance/proxy/src/GPBMetadata/Google/Bigtable/Testproxy/TestProxy.php b/Bigtable/tests/Conformance/proxy/src/GPBMetadata/Google/Bigtable/Testproxy/TestProxy.php
new file mode 100644
index 000000000000..707438f15a99
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/GPBMetadata/Google/Bigtable/Testproxy/TestProxy.php
@@ -0,0 +1,30 @@
+internalAddGeneratedFile(
+ "\x0A\xFC\x1F\x0A*google/bigtable/testproxy/test_proxy.proto\x12\x19google.bigtable.testproxy\x1A!google/bigtable/v2/bigtable.proto\x1A\x1Dgoogle/bigtable/v2/data.proto\x1A\x1Egoogle/protobuf/duration.proto\x1A\x17google/rpc/status.proto\"\xDA\x03\x0A\x13CreateClientRequest\x12\x11\x0A\x09client_id\x18\x01 \x01(\x09\x12\x13\x0A\x0Bdata_target\x18\x02 \x01(\x09\x12\x12\x0A\x0Aproject_id\x18\x03 \x01(\x09\x12\x13\x0A\x0Binstance_id\x18\x04 \x01(\x09\x12\x16\x0A\x0Eapp_profile_id\x18\x05 \x01(\x09\x128\x0A\x15per_operation_timeout\x18\x06 \x01(\x0B2\x19.google.protobuf.Duration\x12Q\x0A\x17optional_feature_config\x18\x07 \x01(\x0E20.google.bigtable.testproxy.OptionalFeatureConfig\x12X\x0A\x10security_options\x18\x08 \x01(\x0B2>.google.bigtable.testproxy.CreateClientRequest.SecurityOptions\x1As\x0A\x0FSecurityOptions\x12\x14\x0A\x0Caccess_token\x18\x01 \x01(\x09\x12\x0F\x0A\x07use_ssl\x18\x02 \x01(\x08\x12\x1D\x0A\x15ssl_endpoint_override\x18\x03 \x01(\x09\x12\x1A\x0A\x12ssl_root_certs_pem\x18\x04 \x01(\x09\"\x16\x0A\x14CreateClientResponse\"'\x0A\x12CloseClientRequest\x12\x11\x0A\x09client_id\x18\x01 \x01(\x09\"\x15\x0A\x13CloseClientResponse\"(\x0A\x13RemoveClientRequest\x12\x11\x0A\x09client_id\x18\x01 \x01(\x09\"\x16\x0A\x14RemoveClientResponse\"w\x0A\x0EReadRowRequest\x12\x11\x0A\x09client_id\x18\x01 \x01(\x09\x12\x12\x0A\x0Atable_name\x18\x04 \x01(\x09\x12\x0F\x0A\x07row_key\x18\x02 \x01(\x09\x12-\x0A\x06filter\x18\x03 \x01(\x0B2\x1D.google.bigtable.v2.RowFilter\"U\x0A\x09RowResult\x12\"\x0A\x06status\x18\x01 \x01(\x0B2\x12.google.rpc.Status\x12\$\x0A\x03row\x18\x02 \x01(\x0B2\x17.google.bigtable.v2.Row\"u\x0A\x0FReadRowsRequest\x12\x11\x0A\x09client_id\x18\x01 \x01(\x09\x124\x0A\x07request\x18\x02 \x01(\x0B2#.google.bigtable.v2.ReadRowsRequest\x12\x19\x0A\x11cancel_after_rows\x18\x03 \x01(\x05\"W\x0A\x0ARowsResult\x12\"\x0A\x06status\x18\x01 \x01(\x0B2\x12.google.rpc.Status\x12%\x0A\x04rows\x18\x02 \x03(\x0B2\x17.google.bigtable.v2.Row\"\\\x0A\x10MutateRowRequest\x12\x11\x0A\x09client_id\x18\x01 \x01(\x09\x125\x0A\x07request\x18\x02 \x01(\x0B2\$.google.bigtable.v2.MutateRowRequest\"5\x0A\x0FMutateRowResult\x12\"\x0A\x06status\x18\x01 \x01(\x0B2\x12.google.rpc.Status\"^\x0A\x11MutateRowsRequest\x12\x11\x0A\x09client_id\x18\x01 \x01(\x09\x126\x0A\x07request\x18\x02 \x01(\x0B2%.google.bigtable.v2.MutateRowsRequest\"u\x0A\x10MutateRowsResult\x12\"\x0A\x06status\x18\x01 \x01(\x0B2\x12.google.rpc.Status\x12=\x0A\x07entries\x18\x02 \x03(\x0B2,.google.bigtable.v2.MutateRowsResponse.Entry\"l\x0A\x18CheckAndMutateRowRequest\x12\x11\x0A\x09client_id\x18\x01 \x01(\x09\x12=\x0A\x07request\x18\x02 \x01(\x0B2,.google.bigtable.v2.CheckAndMutateRowRequest\"|\x0A\x17CheckAndMutateRowResult\x12\"\x0A\x06status\x18\x01 \x01(\x0B2\x12.google.rpc.Status\x12=\x0A\x06result\x18\x02 \x01(\x0B2-.google.bigtable.v2.CheckAndMutateRowResponse\"d\x0A\x14SampleRowKeysRequest\x12\x11\x0A\x09client_id\x18\x01 \x01(\x09\x129\x0A\x07request\x18\x02 \x01(\x0B2(.google.bigtable.v2.SampleRowKeysRequest\"u\x0A\x13SampleRowKeysResult\x12\"\x0A\x06status\x18\x01 \x01(\x0B2\x12.google.rpc.Status\x12:\x0A\x07samples\x18\x02 \x03(\x0B2).google.bigtable.v2.SampleRowKeysResponse\"n\x0A\x19ReadModifyWriteRowRequest\x12\x11\x0A\x09client_id\x18\x01 \x01(\x09\x12>\x0A\x07request\x18\x02 \x01(\x0B2-.google.bigtable.v2.ReadModifyWriteRowRequest\"b\x0A\x13ExecuteQueryRequest\x12\x11\x0A\x09client_id\x18\x01 \x01(\x09\x128\x0A\x07request\x18\x02 \x01(\x0B2'.google.bigtable.v2.ExecuteQueryRequest\"\xA9\x01\x0A\x12ExecuteQueryResult\x12\"\x0A\x06status\x18\x01 \x01(\x0B2\x12.google.rpc.Status\x12>\x0A\x08metadata\x18\x04 \x01(\x0B2,.google.bigtable.testproxy.ResultSetMetadata\x12/\x0A\x04rows\x18\x03 \x03(\x0B2!.google.bigtable.testproxy.SqlRow\"H\x0A\x11ResultSetMetadata\x123\x0A\x07columns\x18\x01 \x03(\x0B2\".google.bigtable.v2.ColumnMetadata\"3\x0A\x06SqlRow\x12)\x0A\x06values\x18\x01 \x03(\x0B2\x19.google.bigtable.v2.Value*d\x0A\x15OptionalFeatureConfig\x12#\x0A\x1FOPTIONAL_FEATURE_CONFIG_DEFAULT\x10\x00\x12&\x0A\"OPTIONAL_FEATURE_CONFIG_ENABLE_ALL\x10\x012\x95\x0A\x0A\x18CloudBigtableV2TestProxy\x12q\x0A\x0CCreateClient\x12..google.bigtable.testproxy.CreateClientRequest\x1A/.google.bigtable.testproxy.CreateClientResponse\"\x00\x12n\x0A\x0BCloseClient\x12-.google.bigtable.testproxy.CloseClientRequest\x1A..google.bigtable.testproxy.CloseClientResponse\"\x00\x12q\x0A\x0CRemoveClient\x12..google.bigtable.testproxy.RemoveClientRequest\x1A/.google.bigtable.testproxy.RemoveClientResponse\"\x00\x12\\\x0A\x07ReadRow\x12).google.bigtable.testproxy.ReadRowRequest\x1A\$.google.bigtable.testproxy.RowResult\"\x00\x12_\x0A\x08ReadRows\x12*.google.bigtable.testproxy.ReadRowsRequest\x1A%.google.bigtable.testproxy.RowsResult\"\x00\x12f\x0A\x09MutateRow\x12+.google.bigtable.testproxy.MutateRowRequest\x1A*.google.bigtable.testproxy.MutateRowResult\"\x00\x12m\x0A\x0EBulkMutateRows\x12,.google.bigtable.testproxy.MutateRowsRequest\x1A+.google.bigtable.testproxy.MutateRowsResult\"\x00\x12~\x0A\x11CheckAndMutateRow\x123.google.bigtable.testproxy.CheckAndMutateRowRequest\x1A2.google.bigtable.testproxy.CheckAndMutateRowResult\"\x00\x12r\x0A\x0DSampleRowKeys\x12/.google.bigtable.testproxy.SampleRowKeysRequest\x1A..google.bigtable.testproxy.SampleRowKeysResult\"\x00\x12r\x0A\x12ReadModifyWriteRow\x124.google.bigtable.testproxy.ReadModifyWriteRowRequest\x1A\$.google.bigtable.testproxy.RowResult\"\x00\x12o\x0A\x0CExecuteQuery\x12..google.bigtable.testproxy.ExecuteQueryRequest\x1A-.google.bigtable.testproxy.ExecuteQueryResult\"\x00\x1A4\xCAA1bigtable-test-proxy-not-accessible.googleapis.comBg\x0A#com.google.cloud.bigtable.testproxyP\x01Z>cloud.google.com/go/bigtable/testproxy/testproxypb;testproxypbb\x06proto3"
+ , true);
+
+ static::$is_initialized = true;
+ }
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CheckAndMutateRowRequest.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CheckAndMutateRowRequest.php
new file mode 100644
index 000000000000..6d3c7792a215
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CheckAndMutateRowRequest.php
@@ -0,0 +1,112 @@
+google.bigtable.testproxy.CheckAndMutateRowRequest
+ */
+class CheckAndMutateRowRequest extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ */
+ protected $client_id = '';
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.CheckAndMutateRowRequest request = 2;
+ */
+ protected $request = null;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $client_id
+ * The ID of the target client object.
+ * @type \Google\Cloud\Bigtable\V2\CheckAndMutateRowRequest $request
+ * The raw request to the Bigtable server.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @return string
+ */
+ public function getClientId()
+ {
+ return $this->client_id;
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setClientId($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->client_id = $var;
+
+ return $this;
+ }
+
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.CheckAndMutateRowRequest request = 2;
+ * @return \Google\Cloud\Bigtable\V2\CheckAndMutateRowRequest|null
+ */
+ public function getRequest()
+ {
+ return $this->request;
+ }
+
+ public function hasRequest()
+ {
+ return isset($this->request);
+ }
+
+ public function clearRequest()
+ {
+ unset($this->request);
+ }
+
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.CheckAndMutateRowRequest request = 2;
+ * @param \Google\Cloud\Bigtable\V2\CheckAndMutateRowRequest $var
+ * @return $this
+ */
+ public function setRequest($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Bigtable\V2\CheckAndMutateRowRequest::class);
+ $this->request = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CheckAndMutateRowResult.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CheckAndMutateRowResult.php
new file mode 100644
index 000000000000..076162568a27
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CheckAndMutateRowResult.php
@@ -0,0 +1,122 @@
+google.bigtable.testproxy.CheckAndMutateRowResult
+ */
+class CheckAndMutateRowResult extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ */
+ protected $status = null;
+ /**
+ * The raw response from the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.CheckAndMutateRowResponse result = 2;
+ */
+ protected $result = null;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type \Google\Rpc\Status $status
+ * The RPC status from the client binding.
+ * @type \Google\Cloud\Bigtable\V2\CheckAndMutateRowResponse $result
+ * The raw response from the Bigtable server.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ * @return \Google\Rpc\Status|null
+ */
+ public function getStatus()
+ {
+ return $this->status;
+ }
+
+ public function hasStatus()
+ {
+ return isset($this->status);
+ }
+
+ public function clearStatus()
+ {
+ unset($this->status);
+ }
+
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ * @param \Google\Rpc\Status $var
+ * @return $this
+ */
+ public function setStatus($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Rpc\Status::class);
+ $this->status = $var;
+
+ return $this;
+ }
+
+ /**
+ * The raw response from the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.CheckAndMutateRowResponse result = 2;
+ * @return \Google\Cloud\Bigtable\V2\CheckAndMutateRowResponse|null
+ */
+ public function getResult()
+ {
+ return $this->result;
+ }
+
+ public function hasResult()
+ {
+ return isset($this->result);
+ }
+
+ public function clearResult()
+ {
+ unset($this->result);
+ }
+
+ /**
+ * The raw response from the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.CheckAndMutateRowResponse result = 2;
+ * @param \Google\Cloud\Bigtable\V2\CheckAndMutateRowResponse $var
+ * @return $this
+ */
+ public function setResult($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Bigtable\V2\CheckAndMutateRowResponse::class);
+ $this->result = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CloseClientRequest.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CloseClientRequest.php
new file mode 100644
index 000000000000..1552575f2560
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CloseClientRequest.php
@@ -0,0 +1,68 @@
+google.bigtable.testproxy.CloseClientRequest
+ */
+class CloseClientRequest extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ */
+ protected $client_id = '';
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $client_id
+ * The ID of the target client object.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @return string
+ */
+ public function getClientId()
+ {
+ return $this->client_id;
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setClientId($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->client_id = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CloseClientResponse.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CloseClientResponse.php
new file mode 100644
index 000000000000..34deeffd6d69
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CloseClientResponse.php
@@ -0,0 +1,34 @@
+google.bigtable.testproxy.CloseClientResponse
+ */
+class CloseClientResponse extends \Google\Protobuf\Internal\Message
+{
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CloudBigtableV2TestProxyInterface.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CloudBigtableV2TestProxyInterface.php
new file mode 100644
index 000000000000..2e96424773da
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CloudBigtableV2TestProxyInterface.php
@@ -0,0 +1,112 @@
+google.bigtable.testproxy.CreateClientRequest
+ */
+class CreateClientRequest extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * A unique ID associated with the client object to be created.
+ *
+ * Generated from protobuf field string client_id = 1;
+ */
+ protected $client_id = '';
+ /**
+ * The "host:port" address of the data API endpoint (i.e. the backend being
+ * proxied to). Example: 127.0.0.1:38543. If you want to connect to a local
+ * emulator via BIGTABLE_EMULATOR_HOST environment variable, you can use
+ * "emulator" instead of "host:port" for this field.
+ *
+ * Generated from protobuf field string data_target = 2;
+ */
+ protected $data_target = '';
+ /**
+ * The project for all calls on this client.
+ *
+ * Generated from protobuf field string project_id = 3;
+ */
+ protected $project_id = '';
+ /**
+ * The instance for all calls on this client.
+ *
+ * Generated from protobuf field string instance_id = 4;
+ */
+ protected $instance_id = '';
+ /**
+ * Optional app profile for all calls on this client.
+ * Some client bindings allow specifying the app profile on a per-operation
+ * basis. We don't yet support this in the proxy API, but may in the future.
+ *
+ * Generated from protobuf field string app_profile_id = 5;
+ */
+ protected $app_profile_id = '';
+ /**
+ * If provided, a custom timeout will be set for each API call conducted by
+ * the created client. Otherwise, the default timeout from the client library
+ * will be used. Note that the override applies to all the methods.
+ *
+ * Generated from protobuf field .google.protobuf.Duration per_operation_timeout = 6;
+ */
+ protected $per_operation_timeout = null;
+ /**
+ * Optional config that dictates how the optional features should be enabled
+ * during the client creation. Please check the enum type's docstring above.
+ *
+ * Generated from protobuf field .google.bigtable.testproxy.OptionalFeatureConfig optional_feature_config = 7;
+ */
+ protected $optional_feature_config = 0;
+ /**
+ * Options to allow connecting to backends with channel and/or call
+ * credentials. This is needed internally by Cloud Bigtable's own testing
+ * frameworks.It is not necessary to support these fields for client
+ * conformance testing.
+ * WARNING: this allows the proxy to connect to a real production
+ * CBT backend with the right options, however, the proxy itself is insecure
+ * so it is not recommended to use it with real credentials or outside testing
+ * contexts.
+ *
+ * Generated from protobuf field .google.bigtable.testproxy.CreateClientRequest.SecurityOptions security_options = 8;
+ */
+ protected $security_options = null;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $client_id
+ * A unique ID associated with the client object to be created.
+ * @type string $data_target
+ * The "host:port" address of the data API endpoint (i.e. the backend being
+ * proxied to). Example: 127.0.0.1:38543. If you want to connect to a local
+ * emulator via BIGTABLE_EMULATOR_HOST environment variable, you can use
+ * "emulator" instead of "host:port" for this field.
+ * @type string $project_id
+ * The project for all calls on this client.
+ * @type string $instance_id
+ * The instance for all calls on this client.
+ * @type string $app_profile_id
+ * Optional app profile for all calls on this client.
+ * Some client bindings allow specifying the app profile on a per-operation
+ * basis. We don't yet support this in the proxy API, but may in the future.
+ * @type \Google\Protobuf\Duration $per_operation_timeout
+ * If provided, a custom timeout will be set for each API call conducted by
+ * the created client. Otherwise, the default timeout from the client library
+ * will be used. Note that the override applies to all the methods.
+ * @type int $optional_feature_config
+ * Optional config that dictates how the optional features should be enabled
+ * during the client creation. Please check the enum type's docstring above.
+ * @type \Google\Bigtable\Testproxy\CreateClientRequest\SecurityOptions $security_options
+ * Options to allow connecting to backends with channel and/or call
+ * credentials. This is needed internally by Cloud Bigtable's own testing
+ * frameworks.It is not necessary to support these fields for client
+ * conformance testing.
+ * WARNING: this allows the proxy to connect to a real production
+ * CBT backend with the right options, however, the proxy itself is insecure
+ * so it is not recommended to use it with real credentials or outside testing
+ * contexts.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * A unique ID associated with the client object to be created.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @return string
+ */
+ public function getClientId()
+ {
+ return $this->client_id;
+ }
+
+ /**
+ * A unique ID associated with the client object to be created.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setClientId($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->client_id = $var;
+
+ return $this;
+ }
+
+ /**
+ * The "host:port" address of the data API endpoint (i.e. the backend being
+ * proxied to). Example: 127.0.0.1:38543. If you want to connect to a local
+ * emulator via BIGTABLE_EMULATOR_HOST environment variable, you can use
+ * "emulator" instead of "host:port" for this field.
+ *
+ * Generated from protobuf field string data_target = 2;
+ * @return string
+ */
+ public function getDataTarget()
+ {
+ return $this->data_target;
+ }
+
+ /**
+ * The "host:port" address of the data API endpoint (i.e. the backend being
+ * proxied to). Example: 127.0.0.1:38543. If you want to connect to a local
+ * emulator via BIGTABLE_EMULATOR_HOST environment variable, you can use
+ * "emulator" instead of "host:port" for this field.
+ *
+ * Generated from protobuf field string data_target = 2;
+ * @param string $var
+ * @return $this
+ */
+ public function setDataTarget($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->data_target = $var;
+
+ return $this;
+ }
+
+ /**
+ * The project for all calls on this client.
+ *
+ * Generated from protobuf field string project_id = 3;
+ * @return string
+ */
+ public function getProjectId()
+ {
+ return $this->project_id;
+ }
+
+ /**
+ * The project for all calls on this client.
+ *
+ * Generated from protobuf field string project_id = 3;
+ * @param string $var
+ * @return $this
+ */
+ public function setProjectId($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->project_id = $var;
+
+ return $this;
+ }
+
+ /**
+ * The instance for all calls on this client.
+ *
+ * Generated from protobuf field string instance_id = 4;
+ * @return string
+ */
+ public function getInstanceId()
+ {
+ return $this->instance_id;
+ }
+
+ /**
+ * The instance for all calls on this client.
+ *
+ * Generated from protobuf field string instance_id = 4;
+ * @param string $var
+ * @return $this
+ */
+ public function setInstanceId($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->instance_id = $var;
+
+ return $this;
+ }
+
+ /**
+ * Optional app profile for all calls on this client.
+ * Some client bindings allow specifying the app profile on a per-operation
+ * basis. We don't yet support this in the proxy API, but may in the future.
+ *
+ * Generated from protobuf field string app_profile_id = 5;
+ * @return string
+ */
+ public function getAppProfileId()
+ {
+ return $this->app_profile_id;
+ }
+
+ /**
+ * Optional app profile for all calls on this client.
+ * Some client bindings allow specifying the app profile on a per-operation
+ * basis. We don't yet support this in the proxy API, but may in the future.
+ *
+ * Generated from protobuf field string app_profile_id = 5;
+ * @param string $var
+ * @return $this
+ */
+ public function setAppProfileId($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->app_profile_id = $var;
+
+ return $this;
+ }
+
+ /**
+ * If provided, a custom timeout will be set for each API call conducted by
+ * the created client. Otherwise, the default timeout from the client library
+ * will be used. Note that the override applies to all the methods.
+ *
+ * Generated from protobuf field .google.protobuf.Duration per_operation_timeout = 6;
+ * @return \Google\Protobuf\Duration|null
+ */
+ public function getPerOperationTimeout()
+ {
+ return $this->per_operation_timeout;
+ }
+
+ public function hasPerOperationTimeout()
+ {
+ return isset($this->per_operation_timeout);
+ }
+
+ public function clearPerOperationTimeout()
+ {
+ unset($this->per_operation_timeout);
+ }
+
+ /**
+ * If provided, a custom timeout will be set for each API call conducted by
+ * the created client. Otherwise, the default timeout from the client library
+ * will be used. Note that the override applies to all the methods.
+ *
+ * Generated from protobuf field .google.protobuf.Duration per_operation_timeout = 6;
+ * @param \Google\Protobuf\Duration $var
+ * @return $this
+ */
+ public function setPerOperationTimeout($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Protobuf\Duration::class);
+ $this->per_operation_timeout = $var;
+
+ return $this;
+ }
+
+ /**
+ * Optional config that dictates how the optional features should be enabled
+ * during the client creation. Please check the enum type's docstring above.
+ *
+ * Generated from protobuf field .google.bigtable.testproxy.OptionalFeatureConfig optional_feature_config = 7;
+ * @return int
+ */
+ public function getOptionalFeatureConfig()
+ {
+ return $this->optional_feature_config;
+ }
+
+ /**
+ * Optional config that dictates how the optional features should be enabled
+ * during the client creation. Please check the enum type's docstring above.
+ *
+ * Generated from protobuf field .google.bigtable.testproxy.OptionalFeatureConfig optional_feature_config = 7;
+ * @param int $var
+ * @return $this
+ */
+ public function setOptionalFeatureConfig($var)
+ {
+ GPBUtil::checkEnum($var, \Google\Bigtable\Testproxy\OptionalFeatureConfig::class);
+ $this->optional_feature_config = $var;
+
+ return $this;
+ }
+
+ /**
+ * Options to allow connecting to backends with channel and/or call
+ * credentials. This is needed internally by Cloud Bigtable's own testing
+ * frameworks.It is not necessary to support these fields for client
+ * conformance testing.
+ * WARNING: this allows the proxy to connect to a real production
+ * CBT backend with the right options, however, the proxy itself is insecure
+ * so it is not recommended to use it with real credentials or outside testing
+ * contexts.
+ *
+ * Generated from protobuf field .google.bigtable.testproxy.CreateClientRequest.SecurityOptions security_options = 8;
+ * @return \Google\Bigtable\Testproxy\CreateClientRequest\SecurityOptions|null
+ */
+ public function getSecurityOptions()
+ {
+ return $this->security_options;
+ }
+
+ public function hasSecurityOptions()
+ {
+ return isset($this->security_options);
+ }
+
+ public function clearSecurityOptions()
+ {
+ unset($this->security_options);
+ }
+
+ /**
+ * Options to allow connecting to backends with channel and/or call
+ * credentials. This is needed internally by Cloud Bigtable's own testing
+ * frameworks.It is not necessary to support these fields for client
+ * conformance testing.
+ * WARNING: this allows the proxy to connect to a real production
+ * CBT backend with the right options, however, the proxy itself is insecure
+ * so it is not recommended to use it with real credentials or outside testing
+ * contexts.
+ *
+ * Generated from protobuf field .google.bigtable.testproxy.CreateClientRequest.SecurityOptions security_options = 8;
+ * @param \Google\Bigtable\Testproxy\CreateClientRequest\SecurityOptions $var
+ * @return $this
+ */
+ public function setSecurityOptions($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Bigtable\Testproxy\CreateClientRequest\SecurityOptions::class);
+ $this->security_options = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CreateClientRequest/SecurityOptions.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CreateClientRequest/SecurityOptions.php
new file mode 100644
index 000000000000..d5cd343672fa
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CreateClientRequest/SecurityOptions.php
@@ -0,0 +1,196 @@
+google.bigtable.testproxy.CreateClientRequest.SecurityOptions
+ */
+class SecurityOptions extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Access token to use for client credentials. If empty, the client will not
+ * use any call credentials. Certain implementations may require `use_ssl`
+ * to be set when using this.
+ *
+ * Generated from protobuf field string access_token = 1;
+ */
+ protected $access_token = '';
+ /**
+ * Whether to use SSL channel credentials when connecting to the data
+ * endpoint.
+ *
+ * Generated from protobuf field bool use_ssl = 2;
+ */
+ protected $use_ssl = false;
+ /**
+ * If using SSL channel credentials, override the SSL endpoint to match the
+ * host that is specified in the backend's certificate. Also sets the
+ * client's authority header value.
+ *
+ * Generated from protobuf field string ssl_endpoint_override = 3;
+ */
+ protected $ssl_endpoint_override = '';
+ /**
+ * PEM encoding of the server root certificates. If not set, the default
+ * root certs will be used instead. The default can be overridden via the
+ * GRPC_DEFAULT_SSL_ROOTS_FILE_PATH env var.
+ *
+ * Generated from protobuf field string ssl_root_certs_pem = 4;
+ */
+ protected $ssl_root_certs_pem = '';
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $access_token
+ * Access token to use for client credentials. If empty, the client will not
+ * use any call credentials. Certain implementations may require `use_ssl`
+ * to be set when using this.
+ * @type bool $use_ssl
+ * Whether to use SSL channel credentials when connecting to the data
+ * endpoint.
+ * @type string $ssl_endpoint_override
+ * If using SSL channel credentials, override the SSL endpoint to match the
+ * host that is specified in the backend's certificate. Also sets the
+ * client's authority header value.
+ * @type string $ssl_root_certs_pem
+ * PEM encoding of the server root certificates. If not set, the default
+ * root certs will be used instead. The default can be overridden via the
+ * GRPC_DEFAULT_SSL_ROOTS_FILE_PATH env var.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Access token to use for client credentials. If empty, the client will not
+ * use any call credentials. Certain implementations may require `use_ssl`
+ * to be set when using this.
+ *
+ * Generated from protobuf field string access_token = 1;
+ * @return string
+ */
+ public function getAccessToken()
+ {
+ return $this->access_token;
+ }
+
+ /**
+ * Access token to use for client credentials. If empty, the client will not
+ * use any call credentials. Certain implementations may require `use_ssl`
+ * to be set when using this.
+ *
+ * Generated from protobuf field string access_token = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setAccessToken($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->access_token = $var;
+
+ return $this;
+ }
+
+ /**
+ * Whether to use SSL channel credentials when connecting to the data
+ * endpoint.
+ *
+ * Generated from protobuf field bool use_ssl = 2;
+ * @return bool
+ */
+ public function getUseSsl()
+ {
+ return $this->use_ssl;
+ }
+
+ /**
+ * Whether to use SSL channel credentials when connecting to the data
+ * endpoint.
+ *
+ * Generated from protobuf field bool use_ssl = 2;
+ * @param bool $var
+ * @return $this
+ */
+ public function setUseSsl($var)
+ {
+ GPBUtil::checkBool($var);
+ $this->use_ssl = $var;
+
+ return $this;
+ }
+
+ /**
+ * If using SSL channel credentials, override the SSL endpoint to match the
+ * host that is specified in the backend's certificate. Also sets the
+ * client's authority header value.
+ *
+ * Generated from protobuf field string ssl_endpoint_override = 3;
+ * @return string
+ */
+ public function getSslEndpointOverride()
+ {
+ return $this->ssl_endpoint_override;
+ }
+
+ /**
+ * If using SSL channel credentials, override the SSL endpoint to match the
+ * host that is specified in the backend's certificate. Also sets the
+ * client's authority header value.
+ *
+ * Generated from protobuf field string ssl_endpoint_override = 3;
+ * @param string $var
+ * @return $this
+ */
+ public function setSslEndpointOverride($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->ssl_endpoint_override = $var;
+
+ return $this;
+ }
+
+ /**
+ * PEM encoding of the server root certificates. If not set, the default
+ * root certs will be used instead. The default can be overridden via the
+ * GRPC_DEFAULT_SSL_ROOTS_FILE_PATH env var.
+ *
+ * Generated from protobuf field string ssl_root_certs_pem = 4;
+ * @return string
+ */
+ public function getSslRootCertsPem()
+ {
+ return $this->ssl_root_certs_pem;
+ }
+
+ /**
+ * PEM encoding of the server root certificates. If not set, the default
+ * root certs will be used instead. The default can be overridden via the
+ * GRPC_DEFAULT_SSL_ROOTS_FILE_PATH env var.
+ *
+ * Generated from protobuf field string ssl_root_certs_pem = 4;
+ * @param string $var
+ * @return $this
+ */
+ public function setSslRootCertsPem($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->ssl_root_certs_pem = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CreateClientResponse.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CreateClientResponse.php
new file mode 100644
index 000000000000..4b8c558f74d3
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/CreateClientResponse.php
@@ -0,0 +1,34 @@
+google.bigtable.testproxy.CreateClientResponse
+ */
+class CreateClientResponse extends \Google\Protobuf\Internal\Message
+{
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ExecuteQueryRequest.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ExecuteQueryRequest.php
new file mode 100644
index 000000000000..daf5025f0fb1
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ExecuteQueryRequest.php
@@ -0,0 +1,112 @@
+google.bigtable.testproxy.ExecuteQueryRequest
+ */
+class ExecuteQueryRequest extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ */
+ protected $client_id = '';
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.ExecuteQueryRequest request = 2;
+ */
+ protected $request = null;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $client_id
+ * The ID of the target client object.
+ * @type \Google\Cloud\Bigtable\V2\ExecuteQueryRequest $request
+ * The raw request to the Bigtable server.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @return string
+ */
+ public function getClientId()
+ {
+ return $this->client_id;
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setClientId($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->client_id = $var;
+
+ return $this;
+ }
+
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.ExecuteQueryRequest request = 2;
+ * @return \Google\Cloud\Bigtable\V2\ExecuteQueryRequest|null
+ */
+ public function getRequest()
+ {
+ return $this->request;
+ }
+
+ public function hasRequest()
+ {
+ return isset($this->request);
+ }
+
+ public function clearRequest()
+ {
+ unset($this->request);
+ }
+
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.ExecuteQueryRequest request = 2;
+ * @param \Google\Cloud\Bigtable\V2\ExecuteQueryRequest $var
+ * @return $this
+ */
+ public function setRequest($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Bigtable\V2\ExecuteQueryRequest::class);
+ $this->request = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ExecuteQueryResult.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ExecuteQueryResult.php
new file mode 100644
index 000000000000..9201f95df0aa
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ExecuteQueryResult.php
@@ -0,0 +1,156 @@
+google.bigtable.testproxy.ExecuteQueryResult
+ */
+class ExecuteQueryResult extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ */
+ protected $status = null;
+ /**
+ * Name and type information for the query result.
+ *
+ * Generated from protobuf field .google.bigtable.testproxy.ResultSetMetadata metadata = 4;
+ */
+ protected $metadata = null;
+ /**
+ * Encoded version of the ResultSet. Should not contain type information.
+ *
+ * Generated from protobuf field repeated .google.bigtable.testproxy.SqlRow rows = 3;
+ */
+ private $rows;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type \Google\Rpc\Status $status
+ * The RPC status from the client binding.
+ * @type \Google\Bigtable\Testproxy\ResultSetMetadata $metadata
+ * Name and type information for the query result.
+ * @type array<\Google\Bigtable\Testproxy\SqlRow>|\Google\Protobuf\Internal\RepeatedField $rows
+ * Encoded version of the ResultSet. Should not contain type information.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ * @return \Google\Rpc\Status|null
+ */
+ public function getStatus()
+ {
+ return $this->status;
+ }
+
+ public function hasStatus()
+ {
+ return isset($this->status);
+ }
+
+ public function clearStatus()
+ {
+ unset($this->status);
+ }
+
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ * @param \Google\Rpc\Status $var
+ * @return $this
+ */
+ public function setStatus($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Rpc\Status::class);
+ $this->status = $var;
+
+ return $this;
+ }
+
+ /**
+ * Name and type information for the query result.
+ *
+ * Generated from protobuf field .google.bigtable.testproxy.ResultSetMetadata metadata = 4;
+ * @return \Google\Bigtable\Testproxy\ResultSetMetadata|null
+ */
+ public function getMetadata()
+ {
+ return $this->metadata;
+ }
+
+ public function hasMetadata()
+ {
+ return isset($this->metadata);
+ }
+
+ public function clearMetadata()
+ {
+ unset($this->metadata);
+ }
+
+ /**
+ * Name and type information for the query result.
+ *
+ * Generated from protobuf field .google.bigtable.testproxy.ResultSetMetadata metadata = 4;
+ * @param \Google\Bigtable\Testproxy\ResultSetMetadata $var
+ * @return $this
+ */
+ public function setMetadata($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Bigtable\Testproxy\ResultSetMetadata::class);
+ $this->metadata = $var;
+
+ return $this;
+ }
+
+ /**
+ * Encoded version of the ResultSet. Should not contain type information.
+ *
+ * Generated from protobuf field repeated .google.bigtable.testproxy.SqlRow rows = 3;
+ * @return \Google\Protobuf\Internal\RepeatedField
+ */
+ public function getRows()
+ {
+ return $this->rows;
+ }
+
+ /**
+ * Encoded version of the ResultSet. Should not contain type information.
+ *
+ * Generated from protobuf field repeated .google.bigtable.testproxy.SqlRow rows = 3;
+ * @param array<\Google\Bigtable\Testproxy\SqlRow>|\Google\Protobuf\Internal\RepeatedField $var
+ * @return $this
+ */
+ public function setRows($var)
+ {
+ $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Bigtable\Testproxy\SqlRow::class);
+ $this->rows = $arr;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/MutateRowRequest.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/MutateRowRequest.php
new file mode 100644
index 000000000000..6498e8e93d9e
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/MutateRowRequest.php
@@ -0,0 +1,112 @@
+google.bigtable.testproxy.MutateRowRequest
+ */
+class MutateRowRequest extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ */
+ protected $client_id = '';
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.MutateRowRequest request = 2;
+ */
+ protected $request = null;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $client_id
+ * The ID of the target client object.
+ * @type \Google\Cloud\Bigtable\V2\MutateRowRequest $request
+ * The raw request to the Bigtable server.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @return string
+ */
+ public function getClientId()
+ {
+ return $this->client_id;
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setClientId($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->client_id = $var;
+
+ return $this;
+ }
+
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.MutateRowRequest request = 2;
+ * @return \Google\Cloud\Bigtable\V2\MutateRowRequest|null
+ */
+ public function getRequest()
+ {
+ return $this->request;
+ }
+
+ public function hasRequest()
+ {
+ return isset($this->request);
+ }
+
+ public function clearRequest()
+ {
+ unset($this->request);
+ }
+
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.MutateRowRequest request = 2;
+ * @param \Google\Cloud\Bigtable\V2\MutateRowRequest $var
+ * @return $this
+ */
+ public function setRequest($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Bigtable\V2\MutateRowRequest::class);
+ $this->request = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/MutateRowResult.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/MutateRowResult.php
new file mode 100644
index 000000000000..e4a51de8b52d
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/MutateRowResult.php
@@ -0,0 +1,78 @@
+google.bigtable.testproxy.MutateRowResult
+ */
+class MutateRowResult extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ */
+ protected $status = null;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type \Google\Rpc\Status $status
+ * The RPC status from the client binding.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ * @return \Google\Rpc\Status|null
+ */
+ public function getStatus()
+ {
+ return $this->status;
+ }
+
+ public function hasStatus()
+ {
+ return isset($this->status);
+ }
+
+ public function clearStatus()
+ {
+ unset($this->status);
+ }
+
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ * @param \Google\Rpc\Status $var
+ * @return $this
+ */
+ public function setStatus($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Rpc\Status::class);
+ $this->status = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/MutateRowsRequest.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/MutateRowsRequest.php
new file mode 100644
index 000000000000..55ac466512c3
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/MutateRowsRequest.php
@@ -0,0 +1,112 @@
+google.bigtable.testproxy.MutateRowsRequest
+ */
+class MutateRowsRequest extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ */
+ protected $client_id = '';
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.MutateRowsRequest request = 2;
+ */
+ protected $request = null;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $client_id
+ * The ID of the target client object.
+ * @type \Google\Cloud\Bigtable\V2\MutateRowsRequest $request
+ * The raw request to the Bigtable server.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @return string
+ */
+ public function getClientId()
+ {
+ return $this->client_id;
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setClientId($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->client_id = $var;
+
+ return $this;
+ }
+
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.MutateRowsRequest request = 2;
+ * @return \Google\Cloud\Bigtable\V2\MutateRowsRequest|null
+ */
+ public function getRequest()
+ {
+ return $this->request;
+ }
+
+ public function hasRequest()
+ {
+ return isset($this->request);
+ }
+
+ public function clearRequest()
+ {
+ unset($this->request);
+ }
+
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.MutateRowsRequest request = 2;
+ * @param \Google\Cloud\Bigtable\V2\MutateRowsRequest $var
+ * @return $this
+ */
+ public function setRequest($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Bigtable\V2\MutateRowsRequest::class);
+ $this->request = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/MutateRowsResult.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/MutateRowsResult.php
new file mode 100644
index 000000000000..704a2fb0d946
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/MutateRowsResult.php
@@ -0,0 +1,116 @@
+google.bigtable.testproxy.MutateRowsResult
+ */
+class MutateRowsResult extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The RPC status from the client binding, corresponding to the
+ * whole operation.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ */
+ protected $status = null;
+ /**
+ * The results corresponding to the failed rows.
+ *
+ * Generated from protobuf field repeated .google.bigtable.v2.MutateRowsResponse.Entry entries = 2;
+ */
+ private $entries;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type \Google\Rpc\Status $status
+ * The RPC status from the client binding, corresponding to the
+ * whole operation.
+ * @type array<\Google\Cloud\Bigtable\V2\MutateRowsResponse\Entry>|\Google\Protobuf\Internal\RepeatedField $entries
+ * The results corresponding to the failed rows.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The RPC status from the client binding, corresponding to the
+ * whole operation.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ * @return \Google\Rpc\Status|null
+ */
+ public function getStatus()
+ {
+ return $this->status;
+ }
+
+ public function hasStatus()
+ {
+ return isset($this->status);
+ }
+
+ public function clearStatus()
+ {
+ unset($this->status);
+ }
+
+ /**
+ * The RPC status from the client binding, corresponding to the
+ * whole operation.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ * @param \Google\Rpc\Status $var
+ * @return $this
+ */
+ public function setStatus($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Rpc\Status::class);
+ $this->status = $var;
+
+ return $this;
+ }
+
+ /**
+ * The results corresponding to the failed rows.
+ *
+ * Generated from protobuf field repeated .google.bigtable.v2.MutateRowsResponse.Entry entries = 2;
+ * @return \Google\Protobuf\Internal\RepeatedField
+ */
+ public function getEntries()
+ {
+ return $this->entries;
+ }
+
+ /**
+ * The results corresponding to the failed rows.
+ *
+ * Generated from protobuf field repeated .google.bigtable.v2.MutateRowsResponse.Entry entries = 2;
+ * @param array<\Google\Cloud\Bigtable\V2\MutateRowsResponse\Entry>|\Google\Protobuf\Internal\RepeatedField $var
+ * @return $this
+ */
+ public function setEntries($var)
+ {
+ $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Cloud\Bigtable\V2\MutateRowsResponse\Entry::class);
+ $this->entries = $arr;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/OptionalFeatureConfig.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/OptionalFeatureConfig.php
new file mode 100644
index 000000000000..bc2d13c74aa9
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/OptionalFeatureConfig.php
@@ -0,0 +1,54 @@
+google.bigtable.testproxy.OptionalFeatureConfig
+ */
+class OptionalFeatureConfig
+{
+ /**
+ * Generated from protobuf enum OPTIONAL_FEATURE_CONFIG_DEFAULT = 0;
+ */
+ const OPTIONAL_FEATURE_CONFIG_DEFAULT = 0;
+ /**
+ * Generated from protobuf enum OPTIONAL_FEATURE_CONFIG_ENABLE_ALL = 1;
+ */
+ const OPTIONAL_FEATURE_CONFIG_ENABLE_ALL = 1;
+
+ private static $valueToName = [
+ self::OPTIONAL_FEATURE_CONFIG_DEFAULT => 'OPTIONAL_FEATURE_CONFIG_DEFAULT',
+ self::OPTIONAL_FEATURE_CONFIG_ENABLE_ALL => 'OPTIONAL_FEATURE_CONFIG_ENABLE_ALL',
+ ];
+
+ public static function name($value)
+ {
+ if (!isset(self::$valueToName[$value])) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no name defined for value %s', __CLASS__, $value));
+ }
+ return self::$valueToName[$value];
+ }
+
+
+ public static function value($name)
+ {
+ $const = __CLASS__ . '::' . strtoupper($name);
+ if (!defined($const)) {
+ throw new UnexpectedValueException(sprintf(
+ 'Enum %s has no value defined for name %s', __CLASS__, $name));
+ }
+ return constant($const);
+ }
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ReadModifyWriteRowRequest.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ReadModifyWriteRowRequest.php
new file mode 100644
index 000000000000..d7f1e97201fb
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ReadModifyWriteRowRequest.php
@@ -0,0 +1,112 @@
+google.bigtable.testproxy.ReadModifyWriteRowRequest
+ */
+class ReadModifyWriteRowRequest extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ */
+ protected $client_id = '';
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.ReadModifyWriteRowRequest request = 2;
+ */
+ protected $request = null;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $client_id
+ * The ID of the target client object.
+ * @type \Google\Cloud\Bigtable\V2\ReadModifyWriteRowRequest $request
+ * The raw request to the Bigtable server.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @return string
+ */
+ public function getClientId()
+ {
+ return $this->client_id;
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setClientId($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->client_id = $var;
+
+ return $this;
+ }
+
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.ReadModifyWriteRowRequest request = 2;
+ * @return \Google\Cloud\Bigtable\V2\ReadModifyWriteRowRequest|null
+ */
+ public function getRequest()
+ {
+ return $this->request;
+ }
+
+ public function hasRequest()
+ {
+ return isset($this->request);
+ }
+
+ public function clearRequest()
+ {
+ unset($this->request);
+ }
+
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.ReadModifyWriteRowRequest request = 2;
+ * @param \Google\Cloud\Bigtable\V2\ReadModifyWriteRowRequest $var
+ * @return $this
+ */
+ public function setRequest($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Bigtable\V2\ReadModifyWriteRowRequest::class);
+ $this->request = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ReadRowRequest.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ReadRowRequest.php
new file mode 100644
index 000000000000..253ebb7de17d
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ReadRowRequest.php
@@ -0,0 +1,188 @@
+google.bigtable.testproxy.ReadRowRequest
+ */
+class ReadRowRequest extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ */
+ protected $client_id = '';
+ /**
+ * The unique name of the table from which to read the row.
+ * Values are of the form
+ * `projects//instances//tables/`.
+ *
+ * Generated from protobuf field string table_name = 4;
+ */
+ protected $table_name = '';
+ /**
+ * The row key of the target row.
+ *
+ * Generated from protobuf field string row_key = 2;
+ */
+ protected $row_key = '';
+ /**
+ * The row filter to be applied to the target row.
+ *
+ * Generated from protobuf field .google.bigtable.v2.RowFilter filter = 3;
+ */
+ protected $filter = null;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $client_id
+ * The ID of the target client object.
+ * @type string $table_name
+ * The unique name of the table from which to read the row.
+ * Values are of the form
+ * `projects//instances//tables/`.
+ * @type string $row_key
+ * The row key of the target row.
+ * @type \Google\Cloud\Bigtable\V2\RowFilter $filter
+ * The row filter to be applied to the target row.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @return string
+ */
+ public function getClientId()
+ {
+ return $this->client_id;
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setClientId($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->client_id = $var;
+
+ return $this;
+ }
+
+ /**
+ * The unique name of the table from which to read the row.
+ * Values are of the form
+ * `projects//instances//tables/`.
+ *
+ * Generated from protobuf field string table_name = 4;
+ * @return string
+ */
+ public function getTableName()
+ {
+ return $this->table_name;
+ }
+
+ /**
+ * The unique name of the table from which to read the row.
+ * Values are of the form
+ * `projects//instances//tables/`.
+ *
+ * Generated from protobuf field string table_name = 4;
+ * @param string $var
+ * @return $this
+ */
+ public function setTableName($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->table_name = $var;
+
+ return $this;
+ }
+
+ /**
+ * The row key of the target row.
+ *
+ * Generated from protobuf field string row_key = 2;
+ * @return string
+ */
+ public function getRowKey()
+ {
+ return $this->row_key;
+ }
+
+ /**
+ * The row key of the target row.
+ *
+ * Generated from protobuf field string row_key = 2;
+ * @param string $var
+ * @return $this
+ */
+ public function setRowKey($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->row_key = $var;
+
+ return $this;
+ }
+
+ /**
+ * The row filter to be applied to the target row.
+ *
+ * Generated from protobuf field .google.bigtable.v2.RowFilter filter = 3;
+ * @return \Google\Cloud\Bigtable\V2\RowFilter|null
+ */
+ public function getFilter()
+ {
+ return $this->filter;
+ }
+
+ public function hasFilter()
+ {
+ return isset($this->filter);
+ }
+
+ public function clearFilter()
+ {
+ unset($this->filter);
+ }
+
+ /**
+ * The row filter to be applied to the target row.
+ *
+ * Generated from protobuf field .google.bigtable.v2.RowFilter filter = 3;
+ * @param \Google\Cloud\Bigtable\V2\RowFilter $var
+ * @return $this
+ */
+ public function setFilter($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Bigtable\V2\RowFilter::class);
+ $this->filter = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ReadRowsRequest.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ReadRowsRequest.php
new file mode 100644
index 000000000000..3f9d163c796d
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ReadRowsRequest.php
@@ -0,0 +1,150 @@
+google.bigtable.testproxy.ReadRowsRequest
+ */
+class ReadRowsRequest extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ */
+ protected $client_id = '';
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.ReadRowsRequest request = 2;
+ */
+ protected $request = null;
+ /**
+ * The streaming read can be canceled before all items are seen.
+ * Has no effect if non-positive.
+ *
+ * Generated from protobuf field int32 cancel_after_rows = 3;
+ */
+ protected $cancel_after_rows = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $client_id
+ * The ID of the target client object.
+ * @type \Google\Cloud\Bigtable\V2\ReadRowsRequest $request
+ * The raw request to the Bigtable server.
+ * @type int $cancel_after_rows
+ * The streaming read can be canceled before all items are seen.
+ * Has no effect if non-positive.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @return string
+ */
+ public function getClientId()
+ {
+ return $this->client_id;
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setClientId($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->client_id = $var;
+
+ return $this;
+ }
+
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.ReadRowsRequest request = 2;
+ * @return \Google\Cloud\Bigtable\V2\ReadRowsRequest|null
+ */
+ public function getRequest()
+ {
+ return $this->request;
+ }
+
+ public function hasRequest()
+ {
+ return isset($this->request);
+ }
+
+ public function clearRequest()
+ {
+ unset($this->request);
+ }
+
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.ReadRowsRequest request = 2;
+ * @param \Google\Cloud\Bigtable\V2\ReadRowsRequest $var
+ * @return $this
+ */
+ public function setRequest($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Bigtable\V2\ReadRowsRequest::class);
+ $this->request = $var;
+
+ return $this;
+ }
+
+ /**
+ * The streaming read can be canceled before all items are seen.
+ * Has no effect if non-positive.
+ *
+ * Generated from protobuf field int32 cancel_after_rows = 3;
+ * @return int
+ */
+ public function getCancelAfterRows()
+ {
+ return $this->cancel_after_rows;
+ }
+
+ /**
+ * The streaming read can be canceled before all items are seen.
+ * Has no effect if non-positive.
+ *
+ * Generated from protobuf field int32 cancel_after_rows = 3;
+ * @param int $var
+ * @return $this
+ */
+ public function setCancelAfterRows($var)
+ {
+ GPBUtil::checkInt32($var);
+ $this->cancel_after_rows = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/RemoveClientRequest.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/RemoveClientRequest.php
new file mode 100644
index 000000000000..ee50fd66275f
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/RemoveClientRequest.php
@@ -0,0 +1,68 @@
+google.bigtable.testproxy.RemoveClientRequest
+ */
+class RemoveClientRequest extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ */
+ protected $client_id = '';
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $client_id
+ * The ID of the target client object.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @return string
+ */
+ public function getClientId()
+ {
+ return $this->client_id;
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setClientId($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->client_id = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/RemoveClientResponse.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/RemoveClientResponse.php
new file mode 100644
index 000000000000..38e7b91aaebb
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/RemoveClientResponse.php
@@ -0,0 +1,34 @@
+google.bigtable.testproxy.RemoveClientResponse
+ */
+class RemoveClientResponse extends \Google\Protobuf\Internal\Message
+{
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ResultSetMetadata.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ResultSetMetadata.php
new file mode 100644
index 000000000000..e98ee5da55ff
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/ResultSetMetadata.php
@@ -0,0 +1,68 @@
+google.bigtable.testproxy.ResultSetMetadata
+ */
+class ResultSetMetadata extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Column metadata for each column inthe query result.
+ *
+ * Generated from protobuf field repeated .google.bigtable.v2.ColumnMetadata columns = 1;
+ */
+ private $columns;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type array<\Google\Cloud\Bigtable\V2\ColumnMetadata>|\Google\Protobuf\Internal\RepeatedField $columns
+ * Column metadata for each column inthe query result.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Column metadata for each column inthe query result.
+ *
+ * Generated from protobuf field repeated .google.bigtable.v2.ColumnMetadata columns = 1;
+ * @return \Google\Protobuf\Internal\RepeatedField
+ */
+ public function getColumns()
+ {
+ return $this->columns;
+ }
+
+ /**
+ * Column metadata for each column inthe query result.
+ *
+ * Generated from protobuf field repeated .google.bigtable.v2.ColumnMetadata columns = 1;
+ * @param array<\Google\Cloud\Bigtable\V2\ColumnMetadata>|\Google\Protobuf\Internal\RepeatedField $var
+ * @return $this
+ */
+ public function setColumns($var)
+ {
+ $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Cloud\Bigtable\V2\ColumnMetadata::class);
+ $this->columns = $arr;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/RowResult.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/RowResult.php
new file mode 100644
index 000000000000..eb78ceb04c44
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/RowResult.php
@@ -0,0 +1,123 @@
+google.bigtable.testproxy.RowResult
+ */
+class RowResult extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ */
+ protected $status = null;
+ /**
+ * The contents of a single row.
+ *
+ * Generated from protobuf field .google.bigtable.v2.Row row = 2;
+ */
+ protected $row = null;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type \Google\Rpc\Status $status
+ * The RPC status from the client binding.
+ * @type \Google\Cloud\Bigtable\V2\Row $row
+ * The contents of a single row.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ * @return \Google\Rpc\Status|null
+ */
+ public function getStatus()
+ {
+ return $this->status;
+ }
+
+ public function hasStatus()
+ {
+ return isset($this->status);
+ }
+
+ public function clearStatus()
+ {
+ unset($this->status);
+ }
+
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ * @param \Google\Rpc\Status $var
+ * @return $this
+ */
+ public function setStatus($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Rpc\Status::class);
+ $this->status = $var;
+
+ return $this;
+ }
+
+ /**
+ * The contents of a single row.
+ *
+ * Generated from protobuf field .google.bigtable.v2.Row row = 2;
+ * @return \Google\Cloud\Bigtable\V2\Row|null
+ */
+ public function getRow()
+ {
+ return $this->row;
+ }
+
+ public function hasRow()
+ {
+ return isset($this->row);
+ }
+
+ public function clearRow()
+ {
+ unset($this->row);
+ }
+
+ /**
+ * The contents of a single row.
+ *
+ * Generated from protobuf field .google.bigtable.v2.Row row = 2;
+ * @param \Google\Cloud\Bigtable\V2\Row $var
+ * @return $this
+ */
+ public function setRow($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Bigtable\V2\Row::class);
+ $this->row = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/RowsResult.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/RowsResult.php
new file mode 100644
index 000000000000..65fea315a273
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/RowsResult.php
@@ -0,0 +1,112 @@
+google.bigtable.testproxy.RowsResult
+ */
+class RowsResult extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ */
+ protected $status = null;
+ /**
+ * The contents of rows.
+ *
+ * Generated from protobuf field repeated .google.bigtable.v2.Row rows = 2;
+ */
+ private $rows;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type \Google\Rpc\Status $status
+ * The RPC status from the client binding.
+ * @type array<\Google\Cloud\Bigtable\V2\Row>|\Google\Protobuf\Internal\RepeatedField $rows
+ * The contents of rows.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ * @return \Google\Rpc\Status|null
+ */
+ public function getStatus()
+ {
+ return $this->status;
+ }
+
+ public function hasStatus()
+ {
+ return isset($this->status);
+ }
+
+ public function clearStatus()
+ {
+ unset($this->status);
+ }
+
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ * @param \Google\Rpc\Status $var
+ * @return $this
+ */
+ public function setStatus($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Rpc\Status::class);
+ $this->status = $var;
+
+ return $this;
+ }
+
+ /**
+ * The contents of rows.
+ *
+ * Generated from protobuf field repeated .google.bigtable.v2.Row rows = 2;
+ * @return \Google\Protobuf\Internal\RepeatedField
+ */
+ public function getRows()
+ {
+ return $this->rows;
+ }
+
+ /**
+ * The contents of rows.
+ *
+ * Generated from protobuf field repeated .google.bigtable.v2.Row rows = 2;
+ * @param array<\Google\Cloud\Bigtable\V2\Row>|\Google\Protobuf\Internal\RepeatedField $var
+ * @return $this
+ */
+ public function setRows($var)
+ {
+ $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Cloud\Bigtable\V2\Row::class);
+ $this->rows = $arr;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/SampleRowKeysRequest.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/SampleRowKeysRequest.php
new file mode 100644
index 000000000000..7beb30faccd4
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/SampleRowKeysRequest.php
@@ -0,0 +1,112 @@
+google.bigtable.testproxy.SampleRowKeysRequest
+ */
+class SampleRowKeysRequest extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ */
+ protected $client_id = '';
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.SampleRowKeysRequest request = 2;
+ */
+ protected $request = null;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type string $client_id
+ * The ID of the target client object.
+ * @type \Google\Cloud\Bigtable\V2\SampleRowKeysRequest $request
+ * The raw request to the Bigtable server.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @return string
+ */
+ public function getClientId()
+ {
+ return $this->client_id;
+ }
+
+ /**
+ * The ID of the target client object.
+ *
+ * Generated from protobuf field string client_id = 1;
+ * @param string $var
+ * @return $this
+ */
+ public function setClientId($var)
+ {
+ GPBUtil::checkString($var, True);
+ $this->client_id = $var;
+
+ return $this;
+ }
+
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.SampleRowKeysRequest request = 2;
+ * @return \Google\Cloud\Bigtable\V2\SampleRowKeysRequest|null
+ */
+ public function getRequest()
+ {
+ return $this->request;
+ }
+
+ public function hasRequest()
+ {
+ return isset($this->request);
+ }
+
+ public function clearRequest()
+ {
+ unset($this->request);
+ }
+
+ /**
+ * The raw request to the Bigtable server.
+ *
+ * Generated from protobuf field .google.bigtable.v2.SampleRowKeysRequest request = 2;
+ * @param \Google\Cloud\Bigtable\V2\SampleRowKeysRequest $var
+ * @return $this
+ */
+ public function setRequest($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Cloud\Bigtable\V2\SampleRowKeysRequest::class);
+ $this->request = $var;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/SampleRowKeysResult.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/SampleRowKeysResult.php
new file mode 100644
index 000000000000..f1d27a3d78bd
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/SampleRowKeysResult.php
@@ -0,0 +1,112 @@
+google.bigtable.testproxy.SampleRowKeysResult
+ */
+class SampleRowKeysResult extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ */
+ protected $status = null;
+ /**
+ * The raw responses from the Bigtable server.
+ *
+ * Generated from protobuf field repeated .google.bigtable.v2.SampleRowKeysResponse samples = 2;
+ */
+ private $samples;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type \Google\Rpc\Status $status
+ * The RPC status from the client binding.
+ * @type array<\Google\Cloud\Bigtable\V2\SampleRowKeysResponse>|\Google\Protobuf\Internal\RepeatedField $samples
+ * The raw responses from the Bigtable server.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ * @return \Google\Rpc\Status|null
+ */
+ public function getStatus()
+ {
+ return $this->status;
+ }
+
+ public function hasStatus()
+ {
+ return isset($this->status);
+ }
+
+ public function clearStatus()
+ {
+ unset($this->status);
+ }
+
+ /**
+ * The RPC status from the client binding.
+ *
+ * Generated from protobuf field .google.rpc.Status status = 1;
+ * @param \Google\Rpc\Status $var
+ * @return $this
+ */
+ public function setStatus($var)
+ {
+ GPBUtil::checkMessage($var, \Google\Rpc\Status::class);
+ $this->status = $var;
+
+ return $this;
+ }
+
+ /**
+ * The raw responses from the Bigtable server.
+ *
+ * Generated from protobuf field repeated .google.bigtable.v2.SampleRowKeysResponse samples = 2;
+ * @return \Google\Protobuf\Internal\RepeatedField
+ */
+ public function getSamples()
+ {
+ return $this->samples;
+ }
+
+ /**
+ * The raw responses from the Bigtable server.
+ *
+ * Generated from protobuf field repeated .google.bigtable.v2.SampleRowKeysResponse samples = 2;
+ * @param array<\Google\Cloud\Bigtable\V2\SampleRowKeysResponse>|\Google\Protobuf\Internal\RepeatedField $var
+ * @return $this
+ */
+ public function setSamples($var)
+ {
+ $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Cloud\Bigtable\V2\SampleRowKeysResponse::class);
+ $this->samples = $arr;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/SqlRow.php b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/SqlRow.php
new file mode 100644
index 000000000000..0c24db3ddb75
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Bigtable/Testproxy/SqlRow.php
@@ -0,0 +1,68 @@
+google.bigtable.testproxy.SqlRow
+ */
+class SqlRow extends \Google\Protobuf\Internal\Message
+{
+ /**
+ * Columnar values returned by the query.
+ *
+ * Generated from protobuf field repeated .google.bigtable.v2.Value values = 1;
+ */
+ private $values;
+
+ /**
+ * Constructor.
+ *
+ * @param array $data {
+ * Optional. Data for populating the Message object.
+ *
+ * @type array<\Google\Cloud\Bigtable\V2\Value>|\Google\Protobuf\Internal\RepeatedField $values
+ * Columnar values returned by the query.
+ * }
+ */
+ public function __construct($data = NULL) {
+ \GPBMetadata\Google\Bigtable\Testproxy\TestProxy::initOnce();
+ parent::__construct($data);
+ }
+
+ /**
+ * Columnar values returned by the query.
+ *
+ * Generated from protobuf field repeated .google.bigtable.v2.Value values = 1;
+ * @return \Google\Protobuf\Internal\RepeatedField
+ */
+ public function getValues()
+ {
+ return $this->values;
+ }
+
+ /**
+ * Columnar values returned by the query.
+ *
+ * Generated from protobuf field repeated .google.bigtable.v2.Value values = 1;
+ * @param array<\Google\Cloud\Bigtable\V2\Value>|\Google\Protobuf\Internal\RepeatedField $var
+ * @return $this
+ */
+ public function setValues($var)
+ {
+ $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Cloud\Bigtable\V2\Value::class);
+ $this->values = $arr;
+
+ return $this;
+ }
+
+}
+
diff --git a/Bigtable/tests/Conformance/proxy/src/Google/Cloud/Bigtable/V2/BigtableInterface.php b/Bigtable/tests/Conformance/proxy/src/Google/Cloud/Bigtable/V2/BigtableInterface.php
new file mode 100644
index 000000000000..70de793d2ce0
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/Google/Cloud/Bigtable/V2/BigtableInterface.php
@@ -0,0 +1,103 @@
+_simpleRequest(
+ '/google.bigtable.testproxy.CloudBigtableV2TestProxy/CreateClient',
+ $message,
+ [CreateClientResponse::class, 'decode'],
+ $metadata,
+ $options
+ );
+ }
+}
diff --git a/Bigtable/tests/Conformance/proxy/src/ProxyService.php b/Bigtable/tests/Conformance/proxy/src/ProxyService.php
new file mode 100644
index 000000000000..febe14cc60d0
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/src/ProxyService.php
@@ -0,0 +1,657 @@
+serializer = new Serializer();
+
+ // create a log channel
+ $this->logger = new Logger('name');
+ $this->logger->pushHandler(new StreamHandler('php://stderr'), Level::Debug);
+
+ // create a shared cache between workers
+ // Manual configuration
+ $rpc = RPC::create('tcp://127.0.0.1:6001');
+ $factory = new Factory($rpc);
+
+ $this->cache = $factory->select('memory-cache');
+ }
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param CreateClientRequest $in
+ * @return CreateClientResponse
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function CreateClient(GRPC\ContextInterface $ctx, Testproxy\CreateClientRequest $in): Testproxy\CreateClientResponse
+ {
+ $this->logger->debug($in->serializeToJsonString());
+
+ $this->cache->set($in->getClientId(), $in);
+
+ return new Testproxy\CreateClientResponse();
+ }
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param CloseClientRequest $in
+ * @return CloseClientResponse
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function CloseClient(GRPC\ContextInterface $ctx, Testproxy\CloseClientRequest $in): Testproxy\CloseClientResponse
+ {
+ $this->getClientAndConfig($in->getClientId());
+
+ // Because our caching cannot store open channels, we implement a workaround here to close
+ // the client when its retrieved from the cache.
+ $this->cache->set($in->getClientId() . '-closed', true);
+
+ return new Testproxy\CloseClientResponse();
+ }
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param RemoveClientRequest $in
+ * @return RemoveClientResponse
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function RemoveClient(GRPC\ContextInterface $ctx, Testproxy\RemoveClientRequest $in): Testproxy\RemoveClientResponse
+ {
+ $this->cache->delete($in->getClientId());
+ $this->cache->delete($in->getClientId() . '-closed');
+
+ return new Testproxy\RemoveClientResponse();
+ }
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param ReadRowRequest $in
+ * @return RowResult
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function ReadRow(GRPC\ContextInterface $ctx, Testproxy\ReadRowRequest $in): Testproxy\RowResult
+ {
+ $this->logger->debug($in->serializeToJsonString());
+
+ $out = new Testproxy\RowResult();
+
+ [$client, $config] = $this->getClientAndConfig($in->getClientId());
+
+ if (!$client) {
+ // This is a workaround to simulate when the client is closed.
+ return $out->setStatus(new Status([
+ 'code' => 1,
+ 'message' => 'Client is closed',
+ ]));
+ }
+
+ $parts = BigtableGapicClient::parseName($in->getTableName());
+ $table = $client->table($parts['instance'], $parts['table'], [
+ 'appProfileId' => $config->getAppProfileId(),
+ ]);
+
+ $rowData = $table->readRow($in->getRowKey(), [
+ 'filter' => $in->getFilter(),
+ 'timeoutMillis' => $this->getTimeoutMillis($config->getPerOperationTimeout()),
+ ]);
+
+ if ($rowData) {
+ $row = $this->arrayToRowProto($rowData);
+ $row->setKey($in->getRowKey());
+ $out->setRow($row);
+ } else {
+ $this->logger->debug(json_encode($rowData));
+ }
+
+ return $out;
+ }
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param ReadRowsRequest $in
+ * @return RowsResult
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function ReadRows(GRPC\ContextInterface $ctx, Testproxy\ReadRowsRequest $in): Testproxy\RowsResult
+ {
+ $this->logger->debug($in->serializeToJsonString());
+
+ $out = new Testproxy\RowsResult();
+
+ [$client, $config] = $this->getClientAndConfig($in->getClientId());
+
+ if (!$client) {
+ // This is a workaround to simulate when the client is closed.
+ return $out->setStatus(new Status([
+ 'code' => 1,
+ 'message' => 'Client is closed',
+ ]));
+ }
+
+ $request = $in->getRequest();
+ $parts = BigtableGapicClient::parseName($request->getTableName());
+ $table = $client->table($parts['instance'], $parts['table'], [
+ 'appProfileId' => $config->getAppProfileId(),
+ ]);
+
+ $ranges = [];
+ $rowKeys = [];
+ if ($rowSet = $request->getRows()) {
+ $rowKeys = iterator_to_array($rowSet->getRowKeys());
+ foreach ($rowSet->getRowRanges() as $range) {
+ $this->logger->debug($range->serializeToJsonString());
+ $ranges[] = array_filter([
+ 'startKeyOpen' => $range->getStartKeyOpen(),
+ 'startKeyClosed' => $range->getStartKeyClosed(),
+ 'endKeyOpen' => $range->getEndKeyOpen(),
+ 'endKeyClosed' => $range->getEndKeyClosed(),
+ ]);
+ }
+ }
+
+ $this->logger->debug(json_encode($rowKeys));
+
+ $stream = $table->readRows([
+ 'rowKeys' => $rowKeys,
+ 'rowRanges' => $ranges,
+ 'filter' => $request->getFilter(),
+ 'rowsLimit' => $request->getRowsLimit(),
+ 'timeoutMillis' => $this->getTimeoutMillis($config->getPerOperationTimeout()),
+ ]);
+
+ $rows = [];
+ $rowCount = 0;
+ $cancelAfterRows = $in->getCancelAfterRows();
+ foreach ($stream as $key => $rowData) {
+ $row = $this->arrayToRowProto($rowData);
+ $row->setKey($key);
+ $rows[] = $row;
+ if ($cancelAfterRows && ++$rowCount >= $cancelAfterRows) {
+ break;
+ }
+ }
+
+ $out->setRows($rows);
+
+ $this->logger->debug($out->serializeToJsonString());
+
+ return $out;
+ }
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param MutateRowRequest $in
+ * @return MutateRowResult
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function MutateRow(GRPC\ContextInterface $ctx, Testproxy\MutateRowRequest $in): Testproxy\MutateRowResult
+ {
+ $this->logger->debug($in->serializeToJsonString());
+
+ $out = new Testproxy\MutateRowResult();
+
+ [$client, $config] = $this->getClientAndConfig($in->getClientId());
+
+ if (!$client) {
+ // This is a workaround to simulate when the client is closed.
+ return $out->setStatus(new Status([
+ 'code' => 1,
+ 'message' => 'Client is closed',
+ ]));
+ }
+
+ $request = $in->getRequest();
+ $parts = BigtableGapicClient::parseName($request->getTableName());
+ $table = $client->table($parts['instance'], $parts['table'], [
+ 'appProfileId' => $config->getAppProfileId(),
+ ]);
+
+ try {
+ $table->mutateRow(
+ $request->getRowKey(),
+ $this->protoToMutations($request->getMutations()),
+ ['timeoutMillis' => $this->getTimeoutMillis($config->getPerOperationTimeout())],
+ );
+ } catch (\Google\ApiCore\ApiException $e) {
+ return $out->setStatus(new Status([
+ 'code' => $e->getCode(),
+ 'message' => $e->getMessage(),
+ ]));
+ }
+
+ return $out;
+ }
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param MutateRowsRequest $in
+ * @return MutateRowsResult
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function BulkMutateRows(GRPC\ContextInterface $ctx, Testproxy\MutateRowsRequest $in): Testproxy\MutateRowsResult
+ {
+ $this->logger->debug($in->serializeToJsonString());
+
+ $out = new Testproxy\MutateRowsResult();
+
+ [$client, $config] = $this->getClientAndConfig($in->getClientId());
+
+ if (!$client) {
+ // This is a workaround to simulate when the client is closed.
+ return $out->setStatus(new Status([
+ 'code' => 1,
+ 'message' => 'Client is closed',
+ ]));
+ }
+
+ $request = $in->getRequest();
+ $parts = BigtableGapicClient::parseName($request->getTableName());
+ $table = $client->table($parts['instance'], $parts['table'], [
+ 'appProfileId' => $config->getAppProfileId(),
+ ]);
+
+ $mutations = [];
+ foreach ($request->getEntries() as $entry) {
+ $mutations[$entry->getRowKey()] = $this->protoToMutations($entry->getMutations());
+ }
+
+ try {
+ $table->mutateRows($mutations, [
+ 'timeoutMillis' => $this->getTimeoutMillis($config->getPerOperationTimeout())
+ ]);
+ } catch (BigtableDataOperationException $e) {
+ $failedEntries = [];
+ foreach ($e->getMetadata() as $metadata) {
+ $status = new Status([
+ 'code' => $metadata['statusCode'],
+ 'message' => $metadata['message'],
+ ]);
+ $failedEntries[] = new Entry([
+ 'index' => $metadata['index'],
+ 'status' => $status,
+ ]);
+ }
+ $out->setEntries($failedEntries);
+ } catch (\Google\ApiCore\ApiException $e) {
+ $out = $out->setStatus(new Status([
+ 'code' => $e->getCode(),
+ 'message' => $e->getMessage(),
+ ]));
+ }
+
+ $this->logger->debug($out->serializeToJsonString());
+
+ return $out;
+ }
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param CheckAndMutateRowRequest $in
+ * @return CheckAndMutateRowResult
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function CheckAndMutateRow(GRPC\ContextInterface $ctx, Testproxy\CheckAndMutateRowRequest $in): Testproxy\CheckAndMutateRowResult
+ {
+ $this->logger->debug($in->serializeToJsonString());
+
+ $out = new Testproxy\CheckAndMutateRowResult();
+
+ [$client, $config] = $this->getClientAndConfig($in->getClientId());
+
+ if (!$client) {
+ // This is a workaround to simulate when the client is closed.
+ return $out->setStatus(new Status([
+ 'code' => 1,
+ 'message' => 'Client is closed',
+ ]));
+ }
+
+ $request = $in->getRequest();
+ $parts = BigtableGapicClient::parseName($request->getTableName());
+ $table = $client->table($parts['instance'], $parts['table'], [
+ 'appProfileId' => $config->getAppProfileId(),
+ ]);
+
+ try {
+ $predicateMatched = $table->checkAndMutateRow($request->getRowKey(), [
+ 'trueMutations' => $this->protoToMutations($request->getTrueMutations()),
+ 'falseMutations' => $this->protoToMutations($request->getFalseMutations()),
+ 'timeoutMillis' => $this->getTimeoutMillis($config->getPerOperationTimeout()),
+ ]);
+ } catch (\Google\ApiCore\ApiException $e) {
+ return $out->setStatus(new Status([
+ 'code' => $e->getCode(),
+ 'message' => $e->getMessage(),
+ ]));
+ }
+
+ $result = new CheckAndMutateRowResponse();
+ $result->setPredicateMatched($predicateMatched);
+
+ return $out->setResult($result);
+ }
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param SampleRowKeysRequest $in
+ * @return SampleRowKeysResult
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function SampleRowKeys(GRPC\ContextInterface $ctx, Testproxy\SampleRowKeysRequest $in): Testproxy\SampleRowKeysResult
+ {
+ $this->logger->debug($in->serializeToJsonString());
+
+ $out = new Testproxy\SampleRowKeysResult();
+
+ [$client, $config] = $this->getClientAndConfig($in->getClientId());
+
+ if (!$client) {
+ // This is a workaround to simulate when the client is closed.
+ return $out->setStatus(new Status([
+ 'code' => 1,
+ 'message' => 'Client is closed',
+ ]));
+ }
+
+ $request = $in->getRequest();
+ $parts = BigtableGapicClient::parseName($request->getTableName());
+ $table = $client->table($parts['instance'], $parts['table'], [
+ 'appProfileId' => $config->getAppProfileId(),
+ ]);
+
+ $sampleRows = $table->sampleRowKeys([
+ 'authorizedViewName' => $request->getAuthorizedViewName(),
+ 'timeoutMillis' => $this->getTimeoutMillis($config->getPerOperationTimeout()),
+ ]);
+
+ try {
+ $responses = [];
+ foreach ($sampleRows as $sampleRow) {
+ $response = new SampleRowKeysResponse();
+ $response->setRowKey($sampleRow['rowKey']);
+ $response->setOffsetBytes($sampleRow['offset']);
+ $responses[] = $response;
+ }
+ } catch (\Google\ApiCore\ApiException $e) {
+ return $out->setStatus(new Status([
+ 'code' => $e->getCode(),
+ 'message' => $e->getMessage(),
+ ]));
+ }
+
+ return $out->setSamples($responses);
+ }
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param ReadModifyWriteRowRequest $in
+ * @return RowResult
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function ReadModifyWriteRow(GRPC\ContextInterface $ctx, Testproxy\ReadModifyWriteRowRequest $in): Testproxy\RowResult
+ {
+ $this->logger->debug($in->serializeToJsonString());
+
+ $out = new Testproxy\RowResult();
+
+ [$client, $config] = $this->getClientAndConfig($in->getClientId());
+
+ if (!$client) {
+ // This is a workaround to simulate when the client is closed.
+ return $out->setStatus(new Status([
+ 'code' => 1,
+ 'message' => 'Client is closed',
+ ]));
+ }
+
+ $request = $in->getRequest();
+ $parts = BigtableGapicClient::parseName($request->getTableName());
+ $table = $client->table($parts['instance'], $parts['table'], [
+ 'appProfileId' => $config->getAppProfileId(),
+ ]);
+
+ try {
+ $rowData = $table->readModifyWriteRow(
+ $request->getRowKey(),
+ $this->protoToRowRules($request->getRules()),
+ [
+ 'timeoutMillis' => $this->getTimeoutMillis($config->getPerOperationTimeout()),
+ ]
+ );
+ } catch (\Google\ApiCore\ApiException $e) {
+ return $out->setStatus(new Status([
+ 'code' => $e->getCode(),
+ 'message' => $e->getMessage(),
+ ]));
+ }
+
+ $row = $this->arrayToRowProto($rowData);
+ $row->setKey($request->getRowKey());
+
+ return $out->setRow($row);
+ }
+
+ /**
+ * @param GRPC\ContextInterface $ctx
+ * @param ExecuteQueryRequest $in
+ * @return ExecuteQueryResult
+ *
+ * @throws GRPC\Exception\InvokeException
+ */
+ public function ExecuteQuery(GRPC\ContextInterface $ctx, Testproxy\ExecuteQueryRequest $in): Testproxy\ExecuteQueryResult
+ {
+ $this->logger->debug($in->serializeToJsonString());
+
+ $out = new Testproxy\ExecuteQueryResult();
+
+ [$client, $config] = $this->getClientAndConfig($in->getClientId());
+
+ if (!$client) {
+ // This is a workaround to simulate when the client is closed.
+ return $out->setStatus(new Status([
+ 'code' => 1,
+ 'message' => 'Client is closed',
+ ]));
+ }
+
+ // There is no ExecuteQuery method in the Bigtable handwritten client, so we will test the
+ // GAPIC generated client directly.
+ $client = new BigtableGapicClient([
+ 'projectId' => $config->getProjectId(),
+ 'apiEndpoint' => $config->getDataTarget(),
+ 'credentials' => new InsecureCredentialsWrapper(),
+ 'transportConfig' => [
+ 'grpc' => [
+ 'stubOpts' => [
+ 'credentials' => ChannelCredentials::createInsecure()
+ ]
+ ]
+ ],
+ ]);
+
+ $request = $in->getRequest();
+
+ try {
+ $stream = $client->executeQuery($request);
+ } catch (\Google\ApiCore\ApiException $e) {
+ return $out->setStatus(new Status([
+ 'code' => $e->getCode(),
+ 'message' => $e->getMessage(),
+ ]));
+ }
+
+ $rows = [];
+ $columns = [];
+ /** @var ExecuteQueryResponse $response */
+ foreach ($stream->readAll() as $response) {
+ if ($metadata = $response->getMetadata()) {
+ $columns = $metadata->getProtoSchema()->getColumns();
+ }
+
+ if ($partialResultSet = $response->getResults()) {
+ $partialRows = $partialResultSet->getProtoRowsBatch();
+ $data = $partialRows->getBatchData();
+ $protoRows = new ProtoRows();
+ $protoRows->mergeFromString($data);
+ $row = new Testproxy\SqlRow();
+ $row->setValues($protoRows->getValues());
+ $rows[] = $row;
+ }
+ }
+
+ $out->setRows($rows);
+ $out->setMetadata(new Testproxy\ResultSetMetadata([
+ 'columns' => $columns,
+ ]));
+
+ return $out;
+ }
+
+ /**
+ * @return array{0:?BigtableClient, 1:CreateClientRequest}
+ */
+ private function getClientAndConfig(string $clientId): array
+ {
+ if (!$this->cache->has($clientId)) {
+ throw new \Exception(sprintf('Client ID "%s" not found', $clientId));
+ }
+
+ $config = $this->cache->get($clientId);
+
+ // @see self::CloseClient
+ if ($this->cache->has($clientId . '-closed')) {
+ return [null, $config];
+ }
+
+ $client = new BigtableClient([
+ 'projectId' => $config->getProjectId(),
+ 'apiEndpoint' => $config->getDataTarget(),
+ 'credentials' => new InsecureCredentialsWrapper(),
+ 'transportConfig' => [
+ 'grpc' => [
+ 'stubOpts' => [
+ 'credentials' => ChannelCredentials::createInsecure()
+ ]
+ ]
+ ],
+ ]);
+
+ return [$client, $config];
+ }
+
+ private function getTimeoutMillis(?\Google\Protobuf\Duration $timeout): ?int
+ {
+ if ($timeout === null) {
+ return null;
+ }
+ return ($timeout->getSeconds() * 1000) + ($timeout->getNanos() / 1000000);
+ }
+
+ /**
+ * @param RepeatedField $protoRowRules
+ * @return Mutations
+ */
+ private function protoToMutations(RepeatedField|null $protoMutations): Mutations|null
+ {
+ if (!$protoMutations) {
+ return null;
+ }
+ $mutations = new Mutations();
+ $reflection = new \ReflectionClass($mutations);
+ $property = $reflection->getProperty('mutations');
+ $property->setAccessible(true);
+ $property->setValue($mutations, $protoMutations);
+
+ return $mutations;
+ }
+
+ /**
+ * @param RepeatedField $protoRowRules
+ * @return ReadModifyWriteRowRules
+ */
+ private function protoToRowRules(RepeatedField $protoRowRules): ReadModifyWriteRowRules
+ {
+ $rowRules = new ReadModifyWriteRowRules();
+ $reflection = new \ReflectionClass($rowRules);
+ $property = $reflection->getProperty('rules');
+ $property->setAccessible(true);
+ $property->setValue($rowRules, $protoRowRules);
+
+ return $rowRules;
+ }
+
+ private function arrayToRowProto(array $rowData): Row
+ {
+ $row = new Row();
+ $families = [];
+ foreach ($rowData as $familyName => $qualifiers) {
+ $f = new Family(['name' => $familyName]);
+ $columns = [];
+ foreach ($qualifiers as $qualifier => $values) {
+ $column = new Column(['qualifier' => $qualifier]);
+ $cells = [];
+ foreach ($values as $value) {
+ $cell = new Cell();
+ $cell->setValue($value['value']);
+ $cell->setTimestampMicros($value['timeStamp']);
+ $cell->setLabels($value['labels'] ?: []);
+ $cells[] = $cell;
+ }
+ $column->setCells($cells);
+ $columns[] = $column;
+ }
+ $f->setColumns($columns);
+ $families[] = $f;
+ }
+ return $row->setFamilies($families);
+ }
+}
diff --git a/Bigtable/tests/Conformance/proxy/test_proxy.proto b/Bigtable/tests/Conformance/proxy/test_proxy.proto
new file mode 100644
index 000000000000..f919dc476ee4
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/test_proxy.proto
@@ -0,0 +1,350 @@
+// Copyright 2024 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.
+
+syntax = "proto3";
+
+package google.bigtable.testproxy;
+
+import "google/api/client.proto";
+import "google/bigtable/v2/bigtable.proto";
+import "google/bigtable/v2/data.proto";
+import "google/protobuf/duration.proto";
+import "google/rpc/status.proto";
+
+option go_package = "cloud.google.com/go/bigtable/testproxy/testproxypb;testproxypb";
+option java_multiple_files = true;
+option java_package = "com.google.cloud.bigtable.testproxy";
+
+// A config flag that dictates how the optional features should be enabled
+// during the client creation. The optional features customize how the client
+// interacts with the server, and are defined in
+// https://github.com/googleapis/googleapis/blob/master/google/bigtable/v2/feature_flags.proto
+enum OptionalFeatureConfig {
+ OPTIONAL_FEATURE_CONFIG_DEFAULT = 0;
+
+ OPTIONAL_FEATURE_CONFIG_ENABLE_ALL = 1;
+}
+
+// Request to test proxy service to create a client object.
+message CreateClientRequest {
+ message SecurityOptions {
+ // Access token to use for client credentials. If empty, the client will not
+ // use any call credentials. Certain implementations may require `use_ssl`
+ // to be set when using this.
+ string access_token = 1;
+
+ // Whether to use SSL channel credentials when connecting to the data
+ // endpoint.
+ bool use_ssl = 2;
+
+ // If using SSL channel credentials, override the SSL endpoint to match the
+ // host that is specified in the backend's certificate. Also sets the
+ // client's authority header value.
+ string ssl_endpoint_override = 3;
+
+ // PEM encoding of the server root certificates. If not set, the default
+ // root certs will be used instead. The default can be overridden via the
+ // GRPC_DEFAULT_SSL_ROOTS_FILE_PATH env var.
+ string ssl_root_certs_pem = 4;
+ }
+
+ // A unique ID associated with the client object to be created.
+ string client_id = 1;
+
+ // The "host:port" address of the data API endpoint (i.e. the backend being
+ // proxied to). Example: 127.0.0.1:38543. If you want to connect to a local
+ // emulator via BIGTABLE_EMULATOR_HOST environment variable, you can use
+ // "emulator" instead of "host:port" for this field.
+ string data_target = 2;
+
+ // The project for all calls on this client.
+ string project_id = 3;
+
+ // The instance for all calls on this client.
+ string instance_id = 4;
+
+ // Optional app profile for all calls on this client.
+ // Some client bindings allow specifying the app profile on a per-operation
+ // basis. We don't yet support this in the proxy API, but may in the future.
+ string app_profile_id = 5;
+
+ // If provided, a custom timeout will be set for each API call conducted by
+ // the created client. Otherwise, the default timeout from the client library
+ // will be used. Note that the override applies to all the methods.
+ google.protobuf.Duration per_operation_timeout = 6;
+
+ // Optional config that dictates how the optional features should be enabled
+ // during the client creation. Please check the enum type's docstring above.
+ OptionalFeatureConfig optional_feature_config = 7;
+
+ // Options to allow connecting to backends with channel and/or call
+ // credentials. This is needed internally by Cloud Bigtable's own testing
+ // frameworks.It is not necessary to support these fields for client
+ // conformance testing.
+ //
+ // WARNING: this allows the proxy to connect to a real production
+ // CBT backend with the right options, however, the proxy itself is insecure
+ // so it is not recommended to use it with real credentials or outside testing
+ // contexts.
+ SecurityOptions security_options = 8;
+}
+
+// Response from test proxy service for CreateClientRequest.
+message CreateClientResponse {}
+
+// Request to test proxy service to close a client object.
+message CloseClientRequest {
+ // The ID of the target client object.
+ string client_id = 1;
+}
+
+// Response from test proxy service for CloseClientRequest.
+message CloseClientResponse {}
+
+// Request to test proxy service to remove a client object.
+message RemoveClientRequest {
+ // The ID of the target client object.
+ string client_id = 1;
+}
+
+// Response from test proxy service for RemoveClientRequest.
+message RemoveClientResponse {}
+
+// Request to test proxy service to read a row.
+message ReadRowRequest {
+ // The ID of the target client object.
+ string client_id = 1;
+
+ // The unique name of the table from which to read the row.
+ // Values are of the form
+ // `projects//instances//tables/`.
+ string table_name = 4;
+
+ // The row key of the target row.
+ string row_key = 2;
+
+ // The row filter to be applied to the target row.
+ google.bigtable.v2.RowFilter filter = 3;
+}
+
+// Response from test proxy service for ReadRowRequest or
+// ReadModifyWriteRowRequest.
+message RowResult {
+ // The RPC status from the client binding.
+ google.rpc.Status status = 1;
+
+ // The contents of a single row.
+ google.bigtable.v2.Row row = 2;
+}
+
+// Request to test proxy service to read rows.
+message ReadRowsRequest {
+ // The ID of the target client object.
+ string client_id = 1;
+
+ // The raw request to the Bigtable server.
+ google.bigtable.v2.ReadRowsRequest request = 2;
+
+ // The streaming read can be canceled before all items are seen.
+ // Has no effect if non-positive.
+ int32 cancel_after_rows = 3;
+}
+
+// Response from test proxy service for ReadRowsRequest.
+message RowsResult {
+ // The RPC status from the client binding.
+ google.rpc.Status status = 1;
+
+ // The contents of rows.
+ repeated google.bigtable.v2.Row rows = 2;
+}
+
+// Request to test proxy service to mutate a row.
+message MutateRowRequest {
+ // The ID of the target client object.
+ string client_id = 1;
+
+ // The raw request to the Bigtable server.
+ google.bigtable.v2.MutateRowRequest request = 2;
+}
+
+// Response from test proxy service for MutateRowRequest.
+message MutateRowResult {
+ // The RPC status from the client binding.
+ google.rpc.Status status = 1;
+}
+
+// Request to test proxy service to mutate rows.
+message MutateRowsRequest {
+ // The ID of the target client object.
+ string client_id = 1;
+
+ // The raw request to the Bigtable server.
+ google.bigtable.v2.MutateRowsRequest request = 2;
+}
+
+// Response from test proxy service for MutateRowsRequest.
+message MutateRowsResult {
+ // The RPC status from the client binding, corresponding to the
+ // whole operation.
+ google.rpc.Status status = 1;
+
+ // The results corresponding to the failed rows.
+ repeated google.bigtable.v2.MutateRowsResponse.Entry entries = 2;
+}
+
+// Request to test proxy service to check and mutate a row.
+message CheckAndMutateRowRequest {
+ // The ID of the target client object.
+ string client_id = 1;
+
+ // The raw request to the Bigtable server.
+ google.bigtable.v2.CheckAndMutateRowRequest request = 2;
+}
+
+// Response from test proxy service for CheckAndMutateRowRequest.
+message CheckAndMutateRowResult {
+ // The RPC status from the client binding.
+ google.rpc.Status status = 1;
+
+ // The raw response from the Bigtable server.
+ google.bigtable.v2.CheckAndMutateRowResponse result = 2;
+}
+
+// Request to test proxy service to sample row keys.
+message SampleRowKeysRequest {
+ // The ID of the target client object.
+ string client_id = 1;
+
+ // The raw request to the Bigtable server.
+ google.bigtable.v2.SampleRowKeysRequest request = 2;
+}
+
+// Response from test proxy service for SampleRowKeysRequest.
+message SampleRowKeysResult {
+ // The RPC status from the client binding.
+ google.rpc.Status status = 1;
+
+ // The raw responses from the Bigtable server.
+ repeated google.bigtable.v2.SampleRowKeysResponse samples = 2;
+}
+
+// Request to test proxy service to read modify write a row.
+message ReadModifyWriteRowRequest {
+ // The ID of the target client object.
+ string client_id = 1;
+
+ // The raw request to the Bigtable server.
+ google.bigtable.v2.ReadModifyWriteRowRequest request = 2;
+}
+
+// Request to test proxy service to execute a query.
+message ExecuteQueryRequest {
+ // The ID of the target client object.
+ string client_id = 1;
+
+ // The raw request to the Bigtable server.
+ google.bigtable.v2.ExecuteQueryRequest request = 2;
+}
+
+// Response from test proxy service for ExecuteQueryRequest.
+message ExecuteQueryResult {
+ // The RPC status from the client binding.
+ google.rpc.Status status = 1;
+
+ // Name and type information for the query result.
+ ResultSetMetadata metadata = 4;
+
+ // Encoded version of the ResultSet. Should not contain type information.
+ repeated SqlRow rows = 3;
+}
+
+// Schema information for the query result.
+message ResultSetMetadata {
+ // Column metadata for each column inthe query result.
+ repeated google.bigtable.v2.ColumnMetadata columns = 1;
+}
+
+// Representation of a single row in the query result.
+message SqlRow {
+ // Columnar values returned by the query.
+ repeated google.bigtable.v2.Value values = 1;
+}
+
+// Note that all RPCs are unary, even when the equivalent client binding call
+// may be streaming. This is an intentional simplification.
+//
+// Most methods have sync (default) and async variants. For async variants,
+// the proxy is expected to perform the async operation, then wait for results
+// before delivering them back to the driver client.
+//
+// Operations that may have interesting concurrency characteristics are
+// represented explicitly in the API (see ReadRowsRequest.cancel_after_rows).
+// We include such operations only when they can be meaningfully performed
+// through client bindings.
+//
+// Users should generally avoid setting deadlines for requests to the Proxy
+// because operations are not cancelable. If the deadline is set anyway, please
+// understand that the underlying operation will continue to be executed even
+// after the deadline expires.
+service CloudBigtableV2TestProxy {
+ option (google.api.default_host) =
+ "bigtable-test-proxy-not-accessible.googleapis.com";
+
+ // Client management:
+ //
+ // Creates a client in the proxy.
+ // Each client has its own dedicated channel(s), and can be used concurrently
+ // and independently with other clients.
+ rpc CreateClient(CreateClientRequest) returns (CreateClientResponse) {}
+
+ // Closes a client in the proxy, making it not accept new requests.
+ rpc CloseClient(CloseClientRequest) returns (CloseClientResponse) {}
+
+ // Removes a client in the proxy, making it inaccessible. Client closing
+ // should be done by CloseClient() separately.
+ rpc RemoveClient(RemoveClientRequest) returns (RemoveClientResponse) {}
+
+ // Bigtable operations: for each operation, you should use the synchronous or
+ // asynchronous variant of the client method based on the `use_async_method`
+ // setting of the client instance. For starters, you can choose to implement
+ // one variant, and return UNIMPLEMENTED status for the other.
+ //
+ // Reads a row with the client instance.
+ // The result row may not be present in the response.
+ // Callers should check for it (e.g. calling has_row() in C++).
+ rpc ReadRow(ReadRowRequest) returns (RowResult) {}
+
+ // Reads rows with the client instance.
+ rpc ReadRows(ReadRowsRequest) returns (RowsResult) {}
+
+ // Writes a row with the client instance.
+ rpc MutateRow(MutateRowRequest) returns (MutateRowResult) {}
+
+ // Writes multiple rows with the client instance.
+ rpc BulkMutateRows(MutateRowsRequest) returns (MutateRowsResult) {}
+
+ // Performs a check-and-mutate-row operation with the client instance.
+ rpc CheckAndMutateRow(CheckAndMutateRowRequest)
+ returns (CheckAndMutateRowResult) {}
+
+ // Obtains a row key sampling with the client instance.
+ rpc SampleRowKeys(SampleRowKeysRequest) returns (SampleRowKeysResult) {}
+
+ // Performs a read-modify-write operation with the client.
+ rpc ReadModifyWriteRow(ReadModifyWriteRowRequest) returns (RowResult) {}
+
+ // Executes a BTQL query with the client.
+ rpc ExecuteQuery(ExecuteQueryRequest) returns (ExecuteQueryResult) {}
+}
\ No newline at end of file
diff --git a/Bigtable/tests/Conformance/proxy/worker.php b/Bigtable/tests/Conformance/proxy/worker.php
new file mode 100644
index 000000000000..4eada76b8a3f
--- /dev/null
+++ b/Bigtable/tests/Conformance/proxy/worker.php
@@ -0,0 +1,20 @@
+ true, // optional (default: false)
+]);
+
+$server->registerService(CloudBigtableV2TestProxyInterface::class, new ProxyService());
+
+$server->serve(Worker::create());
diff --git a/Bigtable/tests/Unit/SmartRetriesTest.php b/Bigtable/tests/Unit/SmartRetriesTest.php
index 130df1031ede..74506bbf80a6 100644
--- a/Bigtable/tests/Unit/SmartRetriesTest.php
+++ b/Bigtable/tests/Unit/SmartRetriesTest.php
@@ -777,17 +777,20 @@ public function testMutateRowsShouldNotRetryIfAnyMutationIsNotRetryable()
$expectedFailedMutations[] = [
'rowKey' => 'rk1',
'statusCode' => Code::ABORTED,
- 'message' => 'partial failure'
+ 'message' => 'partial failure',
+ 'index' => 1,
];
$expectedFailedMutations[] = [
'rowKey' => 'rk2',
'statusCode' => Code::UNAUTHENTICATED,
- 'message' => 'partial failure'
+ 'message' => 'partial failure',
+ 'index' => 2,
];
$expectedFailedMutations[] = [
'rowKey' => 'rk3',
'statusCode' => Code::ABORTED,
- 'message' => 'partial failure'
+ 'message' => 'partial failure',
+ 'index' => 3,
];
foreach (range(5, 7) as $rowKey) {
$expectedFailedMutations[] = [
diff --git a/Bigtable/tests/Unit/TableTest.php b/Bigtable/tests/Unit/TableTest.php
index aefc6bcd1bdd..d08f555e6239 100644
--- a/Bigtable/tests/Unit/TableTest.php
+++ b/Bigtable/tests/Unit/TableTest.php
@@ -235,7 +235,8 @@ public function testMutateRowsFailure()
[
'rowKey' => 'rk1',
'statusCode' => Code::INVALID_ARGUMENT,
- 'message' => 'Invalid argument'
+ 'message' => 'Invalid argument',
+ 'index' => 0,
]
];
$this->assertEquals('partial failure', $e->getMessage());
diff --git a/phpcs-ruleset.xml b/phpcs-ruleset.xml
index dbfc4bf3d0d3..f3ce39e0d0c1 100644
--- a/phpcs-ruleset.xml
+++ b/phpcs-ruleset.xml
@@ -22,6 +22,7 @@
AccessContextManager/src/Type
Asset/external
BigQueryDataExchange/src/Common
+ Bigtable/tests/Conformance/proxy/src
Core/src/Testing
GSuiteAddOns/external
OsLogin/src/Common