Skip to content

Commit 9961984

Browse files
committed
impl(bigtable): first group of query conformance tests
1 parent 6375447 commit 9961984

File tree

5 files changed

+198
-1
lines changed

5 files changed

+198
-1
lines changed

.typos.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ extend-exclude = [
6060
"docfx/doxygen2toc_test.cc",
6161
# If we're using a post-download patch file for googleapis.
6262
"external/googleapis.patch",
63+
# Mispelled test names in Bigtable conformance tests
64+
"google/cloud/bigtable/ci/run_conformance_tests_proxy_bazel.sh",
6365
]
6466

6567
[default]

google/cloud/bigtable/ci/run_conformance_tests_proxy_bazel.sh

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,43 @@ go test -v \
4646
-skip "Generic_CloseClient|Generic_DeadlineExceeded|NoRetry_OutOfOrderError_Reverse|Retry_LastScannedRow_Reverse|Retry_WithRetryInfo_OverallDedaline|TestExecuteQuery" \
4747
-proxy_addr=:9999
4848
exit_status=$?
49+
50+
# Run all the ExecuteQuery tests that either work or we plan to skip such as
51+
# CloseClient
52+
go test -v \
53+
-run "TestExecuteQuery" \
54+
-skip "CloseClient|FailsOnEmptyMetadata|FailsOnExecuteQueryMetadata|FailsOnInvalidType|FailsOnNotEnoughData|FailsOnNotEnoughDataWithCompleteRows|FailsOnSuccesfulStreamWithNoToken|ChecksumMismatch|FailsOnTypeMismatch|FailsOnTypeMismatchWithinMap|FailsOnTypeMismatchWithinArray|FailsOnTypeMismatchWithinStruct|FailsOnStructMissingField|RetryTest_WithPlanRefresh|PlanRefresh" \
55+
-proxy_addr=:9999
56+
exit_status=$?
57+
58+
# These next four go test commands group the currently failing ExecuteQuery
59+
# tests into groups that exercise similar functionality and should be worked on
60+
# together.
61+
62+
# Metadata tests b/461232934
63+
#go test -v \
64+
# -run "FailsOnEmptyMetadata|FailsOnExecuteQueryMetadata|FailsOnInvalidType" \
65+
# -proxy_addr=:9999
66+
#exit_status=$?
67+
68+
# Stream reading tests b/461232110
69+
#go test -v \
70+
# -run "FailsOnNotEnoughData|FailsOnNotEnoughDataWithCompleteRows|FailsOnSuccesfulStreamWithNoToken|ChecksumMismatch" \
71+
# -proxy_addr=:9999
72+
#exit_status=$?
73+
74+
# Response/Metadata mismatches b/461233335
75+
#go test -v \
76+
# -run "FailsOnTypeMismatch|FailsOnTypeMismatchWithinMap|FailsOnTypeMismatchWithinArray|FailsOnTypeMismatchWithinStruct|FailsOnStructMissingField" \
77+
# -proxy_addr=:9999
78+
#exit_status=$?
79+
80+
# QueryPlan refresh tests b/461233613
81+
#go test -v \
82+
# -run "RetryTest_WithPlanRefresh|PlanRefresh" \
83+
# -proxy_addr=:9999
84+
#exit_status=$?
85+
4986
# Remove the entire module cache, including unpacked source code of versioned
5087
# dependencies.
5188
go clean -modcache

google/cloud/bigtable/test_proxy/cbt_test_proxy.cc

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "google/cloud/bigtable/test_proxy/cbt_test_proxy.h"
1616
#include "google/cloud/bigtable/cell.h"
17+
#include "google/cloud/bigtable/client.h"
1718
#include "google/cloud/bigtable/idempotent_mutation_policy.h"
1819
#include "google/cloud/bigtable/mutations.h"
1920
#include "google/cloud/bigtable/table.h"
@@ -360,6 +361,70 @@ grpc::Status CbtTestProxy::ReadModifyWriteRow(
360361
return grpc::Status();
361362
}
362363

364+
grpc::Status CbtTestProxy::ExecuteQuery(
365+
grpc::ServerContext*,
366+
google::bigtable::testproxy::ExecuteQueryRequest const* request,
367+
google::bigtable::testproxy::ExecuteQueryResult* response) {
368+
// Retrieve connection
369+
auto const& conn = GetConnection(request->client_id());
370+
if (!conn.ok()) return ToGrpcStatus(std::move(conn).status());
371+
auto client = bigtable::Client(*conn);
372+
auto const& request_proto = request->request();
373+
374+
// Call prepare query
375+
auto instance = MakeInstanceResource(request_proto.instance_name());
376+
// NOLINTNEXTLINE(deprecated-declarations)
377+
bigtable::SqlStatement sql_statement{request_proto.query()};
378+
auto prepared_query =
379+
client.PrepareQuery(*std::move(instance), sql_statement);
380+
if (!prepared_query.ok()) {
381+
*response->mutable_status() = ToRpcStatus(prepared_query.status());
382+
return ::grpc::Status();
383+
}
384+
385+
// Bind parameters
386+
std::unordered_map<std::string, Value> params;
387+
for (auto const& param : request_proto.params()) {
388+
auto value =
389+
bigtable_internal::FromProto(param.second.type(), param.second);
390+
params.insert(std::make_pair(param.first, std::move(value)));
391+
}
392+
auto bound_query = prepared_query->BindParameters(params);
393+
auto bound_query_metadata = bound_query.response()->metadata();
394+
395+
RowStream result = client.ExecuteQuery(std::move(bound_query), {});
396+
397+
Status status;
398+
std::vector<google::bigtable::testproxy::SqlRow> proxy_rows;
399+
for (auto& row : result) {
400+
if (!row.ok()) {
401+
status = row.status();
402+
break;
403+
}
404+
google::bigtable::testproxy::SqlRow proxy_row;
405+
for (auto const& v : row->values()) {
406+
*proxy_row.add_values() = bigtable_internal::ToProto(v).second;
407+
}
408+
proxy_rows.push_back(std::move(proxy_row));
409+
}
410+
411+
if (status.ok()) {
412+
for (auto& p : proxy_rows) {
413+
*response->add_rows() = std::move(p);
414+
}
415+
}
416+
417+
// populate metadata
418+
google::bigtable::testproxy::ResultSetMetadata metadata;
419+
for (auto const& column : bound_query_metadata.proto_schema().columns()) {
420+
*metadata.add_columns() = column;
421+
}
422+
*response->mutable_metadata() = metadata;
423+
424+
*response->mutable_status() = ToRpcStatus(status);
425+
return grpc::Status();
426+
}
427+
363428
StatusOr<std::shared_ptr<DataConnection>> CbtTestProxy::GetConnection(
364429
std::string const& client_id) {
365430
std::lock_guard<std::mutex> lk(mu_);

google/cloud/bigtable/test_proxy/cbt_test_proxy.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ class CbtTestProxy final
9191
::google::bigtable::testproxy::ReadModifyWriteRowRequest const* request,
9292
::google::bigtable::testproxy::RowResult* response) override;
9393

94+
grpc::Status ExecuteQuery(
95+
::grpc::ServerContext* context,
96+
::google::bigtable::testproxy::ExecuteQueryRequest const* request,
97+
::google::bigtable::testproxy::ExecuteQueryResult* response) override;
98+
9499
private:
95100
StatusOr<std::shared_ptr<DataConnection>> GetConnection(
96101
std::string const& client_id);

protos/google/cloud/bigtable/test_proxy/test_proxy.proto

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,47 @@ package google.bigtable.testproxy;
1919
import "google/api/client.proto";
2020
import "google/bigtable/v2/bigtable.proto";
2121
import "google/bigtable/v2/data.proto";
22+
import "google/protobuf/descriptor.proto";
2223
import "google/protobuf/duration.proto";
2324
import "google/rpc/status.proto";
2425

25-
option go_package = "./testproxypb";
26+
option go_package = "cloud.google.com/go/bigtable/testproxy/testproxypb;testproxypb";
2627
option java_multiple_files = true;
2728
option java_package = "com.google.cloud.bigtable.testproxy";
2829

30+
// A config flag that dictates how the optional features should be enabled
31+
// during the client creation. The optional features customize how the client
32+
// interacts with the server, and are defined in
33+
// https://github.com/googleapis/googleapis/blob/master/google/bigtable/v2/feature_flags.proto
34+
enum OptionalFeatureConfig {
35+
OPTIONAL_FEATURE_CONFIG_DEFAULT = 0;
36+
37+
OPTIONAL_FEATURE_CONFIG_ENABLE_ALL = 1;
38+
}
39+
2940
// Request to test proxy service to create a client object.
3041
message CreateClientRequest {
42+
message SecurityOptions {
43+
// Access token to use for client credentials. If empty, the client will not
44+
// use any call credentials. Certain implementations may require `use_ssl`
45+
// to be set when using this.
46+
string access_token = 1;
47+
48+
// Whether to use SSL channel credentials when connecting to the data
49+
// endpoint.
50+
bool use_ssl = 2;
51+
52+
// If using SSL channel credentials, override the SSL endpoint to match the
53+
// host that is specified in the backend's certificate. Also sets the
54+
// client's authority header value.
55+
string ssl_endpoint_override = 3;
56+
57+
// PEM encoding of the server root certificates. If not set, the default
58+
// root certs will be used instead. The default can be overridden via the
59+
// GRPC_DEFAULT_SSL_ROOTS_FILE_PATH env var.
60+
string ssl_root_certs_pem = 4;
61+
}
62+
3163
// A unique ID associated with the client object to be created.
3264
string client_id = 1;
3365

@@ -52,6 +84,21 @@ message CreateClientRequest {
5284
// the created client. Otherwise, the default timeout from the client library
5385
// will be used. Note that the override applies to all the methods.
5486
google.protobuf.Duration per_operation_timeout = 6;
87+
88+
// Optional config that dictates how the optional features should be enabled
89+
// during the client creation. Please check the enum type's docstring above.
90+
OptionalFeatureConfig optional_feature_config = 7;
91+
92+
// Options to allow connecting to backends with channel and/or call
93+
// credentials. This is needed internally by Cloud Bigtable's own testing
94+
// frameworks.It is not necessary to support these fields for client
95+
// conformance testing.
96+
//
97+
// WARNING: this allows the proxy to connect to a real production
98+
// CBT backend with the right options, however, the proxy itself is insecure
99+
// so it is not recommended to use it with real credentials or outside testing
100+
// contexts.
101+
SecurityOptions security_options = 8;
55102
}
56103

57104
// Response from test proxy service for CreateClientRequest.
@@ -203,6 +250,44 @@ message ReadModifyWriteRowRequest {
203250
google.bigtable.v2.ReadModifyWriteRowRequest request = 2;
204251
}
205252

253+
// Request to test proxy service to execute a query.
254+
message ExecuteQueryRequest {
255+
// The ID of the target client object.
256+
string client_id = 1;
257+
258+
// The raw request to the Bigtable server.
259+
google.bigtable.v2.ExecuteQueryRequest request = 2;
260+
261+
// A collection of proto descriptor files for deserializing PROTO/ENUM columns
262+
// in the query result. The descriptor files must be provided in dependency
263+
// order.
264+
google.protobuf.FileDescriptorSet file_descriptor_set = 3;
265+
}
266+
267+
// Response from test proxy service for ExecuteQueryRequest.
268+
message ExecuteQueryResult {
269+
// The RPC status from the client binding.
270+
google.rpc.Status status = 1;
271+
272+
// Name and type information for the query result.
273+
ResultSetMetadata metadata = 4;
274+
275+
// Encoded version of the ResultSet. Should not contain type information.
276+
repeated SqlRow rows = 3;
277+
}
278+
279+
// Schema information for the query result.
280+
message ResultSetMetadata {
281+
// Column metadata for each column inthe query result.
282+
repeated google.bigtable.v2.ColumnMetadata columns = 1;
283+
}
284+
285+
// Representation of a single row in the query result.
286+
message SqlRow {
287+
// Columnar values returned by the query.
288+
repeated google.bigtable.v2.Value values = 1;
289+
}
290+
206291
// Note that all RPCs are unary, even when the equivalent client binding call
207292
// may be streaming. This is an intentional simplification.
208293
//
@@ -265,4 +350,7 @@ service CloudBigtableV2TestProxy {
265350

266351
// Performs a read-modify-write operation with the client.
267352
rpc ReadModifyWriteRow(ReadModifyWriteRowRequest) returns (RowResult) {}
353+
354+
// Executes a BTQL query with the client.
355+
rpc ExecuteQuery(ExecuteQueryRequest) returns (ExecuteQueryResult) {}
268356
}

0 commit comments

Comments
 (0)