From 8c9466456d0daba0c306f26a1b937774ca091c12 Mon Sep 17 00:00:00 2001 From: Justin Beckwith Date: Mon, 3 May 2021 22:16:29 -0700 Subject: [PATCH 01/12] refactor: move module source to root --- grpc-gcp/.eslintignore => .eslintignore | 0 grpc-gcp/.eslintrc.json => .eslintrc.json | 0 .github/workflows/ci.yaml | 6 - .gitignore | 2 +- grpc-gcp/.nycrc => .nycrc | 0 grpc-gcp/.prettierignore => .prettierignore | 0 grpc-gcp/.prettierrc.js => .prettierrc.js | 0 README.md | 115 ++++++++++++++++- grpc-gcp/codegen.sh => codegen.sh | 0 grpc-gcp/README.md | 117 ------------------ grpc-gcp/package.json => package.json | 2 +- {grpc-gcp/protos => protos}/grpc_gcp.proto | 0 .../protos => protos}/test_service.proto | 0 {grpc-gcp/src => src}/channel_ref.ts | 0 {grpc-gcp/src => src}/gcp_channel_factory.ts | 0 {grpc-gcp/src => src}/generated/grpc_gcp.d.ts | 0 {grpc-gcp/src => src}/generated/grpc_gcp.js | 0 {grpc-gcp/src => src}/index.ts | 0 {grpc-gcp/test => test}/.eslintrc.yaml | 0 .../integration/local_service_test.js | 0 .../integration/spanner.grpc.config | 0 .../test => test}/integration/spanner_test.js | 0 .../unit/channel_factory_test.js | 0 grpc-gcp/tsconfig.json => tsconfig.json | 0 24 files changed, 111 insertions(+), 131 deletions(-) rename grpc-gcp/.eslintignore => .eslintignore (100%) rename grpc-gcp/.eslintrc.json => .eslintrc.json (100%) rename grpc-gcp/.nycrc => .nycrc (100%) rename grpc-gcp/.prettierignore => .prettierignore (100%) rename grpc-gcp/.prettierrc.js => .prettierrc.js (100%) rename grpc-gcp/codegen.sh => codegen.sh (100%) delete mode 100644 grpc-gcp/README.md rename grpc-gcp/package.json => package.json (97%) rename {grpc-gcp/protos => protos}/grpc_gcp.proto (100%) rename {grpc-gcp/protos => protos}/test_service.proto (100%) rename {grpc-gcp/src => src}/channel_ref.ts (100%) rename {grpc-gcp/src => src}/gcp_channel_factory.ts (100%) rename {grpc-gcp/src => src}/generated/grpc_gcp.d.ts (100%) rename {grpc-gcp/src => src}/generated/grpc_gcp.js (100%) rename {grpc-gcp/src => src}/index.ts (100%) rename {grpc-gcp/test => test}/.eslintrc.yaml (100%) rename {grpc-gcp/test => test}/integration/local_service_test.js (100%) rename {grpc-gcp/test => test}/integration/spanner.grpc.config (100%) rename {grpc-gcp/test => test}/integration/spanner_test.js (100%) rename {grpc-gcp/test => test}/unit/channel_factory_test.js (100%) rename grpc-gcp/tsconfig.json => tsconfig.json (100%) diff --git a/grpc-gcp/.eslintignore b/.eslintignore similarity index 100% rename from grpc-gcp/.eslintignore rename to .eslintignore diff --git a/grpc-gcp/.eslintrc.json b/.eslintrc.json similarity index 100% rename from grpc-gcp/.eslintrc.json rename to .eslintrc.json diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7365a4d..9a788ba 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -16,9 +16,7 @@ jobs: node-version: ${{ matrix.node }} - run: node --version - run: npm install - working-directory: ./grpc-gcp - run: npm test - working-directory: ./grpc-gcp windows: runs-on: windows-latest steps: @@ -27,9 +25,7 @@ jobs: with: node-version: 14 - run: npm install - working-directory: ./grpc-gcp - run: npm test - working-directory: ./grpc-gcp lint: runs-on: ubuntu-latest steps: @@ -38,6 +34,4 @@ jobs: with: node-version: 10 - run: npm install - working-directory: ./grpc-gcp - run: npm run lint - working-directory: ./grpc-gcp diff --git a/.gitignore b/.gitignore index a1fefca..94c41ba 100644 --- a/.gitignore +++ b/.gitignore @@ -8,5 +8,5 @@ npm-debug.log coverage # generated code -grpc-gcp/test/google +test/google cloudprober/google diff --git a/grpc-gcp/.nycrc b/.nycrc similarity index 100% rename from grpc-gcp/.nycrc rename to .nycrc diff --git a/grpc-gcp/.prettierignore b/.prettierignore similarity index 100% rename from grpc-gcp/.prettierignore rename to .prettierignore diff --git a/grpc-gcp/.prettierrc.js b/.prettierrc.js similarity index 100% rename from grpc-gcp/.prettierrc.js rename to .prettierrc.js diff --git a/README.md b/README.md index 2ae9006..84a2060 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,113 @@ -# gRPC for GCP extensions +# gRPC-GCP for Node.js -Copyright 2018 -[The gRPC Authors](https://github.com/grpc/grpc/blob/master/AUTHORS) +A Node.js module providing grpc supports for Google Cloud APIs. -## About This Repository +## Installation -This repo is created to support GCP specific extensions for gRPC. To use the extension features, please refer to [grpc-gcp](grpc-gcp). +```sh +npm install grpc-gcp --save +``` -This repo also contains supporting infrastructures such as end2end tests and benchmarks for accessing cloud APIs with gRPC client libraries. +## Usage + +Let's use Spanner API as an example. + +First, Create a json file defining API configuration, with ChannelPoolConfig and MethodConfig. + +```json +{ + "channelPool": { + "maxSize": 10, + "maxConcurrentStreamsLowWatermark": 1 + }, + "method": [ + { + "name": [ "/google.spanner.v1.Spanner/CreateSession" ], + "affinity": { + "command": "BIND", + "affinityKey": "name" + } + }, + { + "name": [ "/google.spanner.v1.Spanner/GetSession" ], + "affinity": { + "command": "BOUND", + "affinityKey": "name" + } + }, + { + "name": [ "/google.spanner.v1.Spanner/DeleteSession" ], + "affinity": { + "command": "UNBIND", + "affinityKey": "name" + } + } + ] +} +``` + +Load configuration to ApiConfig. + +```javascript +// @grpc/grpc-js can be used in place of grpc with no changes +var grpc = require('grpc'); +var grpcGcp = require('grpc-gcp')(grpc); +var fs = require('fs'); + +var apiDefinition = JSON.parse(fs.readFileSync('your_api_config_json_file')); +var apiConfig = grpcGcp.createGcpApiConfig(apiDefinition); +``` + +Pass `gcpChannelFactoryOverride` and `gcpCallInvocationTransformer` to channel options when initializing api client. + +```javascript +var channelOptions = { + channelFactoryOverride: grpcGcp.gcpChannelFactoryOverride, + callInvocationTransformer: grpcGcp.gcpCallInvocationTransformer, + gcpApiConfig: apiConfig, +}; + +var client = new SpannerClient( + 'spanner.googleapis.com:443', + channelCreds, + channelOptions +); +``` + +## Build from source + +Download source. + +```sh +git clone https://github.com/GoogleCloudPlatform/grpc-gcp-node.git && cd grpc-gcp-node +``` + +```sh +git submodule update --init --recursive +``` + +Build grpc-gcp. + +```sh +npm install +``` + +## Test + +Setup credentials. See [Getting Started With Authentication](https://cloud.google.com/docs/authentication/getting-started) for more details. + +```sh +export GOOGLE_APPLICATION_CREDENTIALS=path/to/key.json +``` + +Run unit tests. + +```sh +npm test +``` + +Run system tests. + +```sh +npm run system-test +``` diff --git a/grpc-gcp/codegen.sh b/codegen.sh similarity index 100% rename from grpc-gcp/codegen.sh rename to codegen.sh diff --git a/grpc-gcp/README.md b/grpc-gcp/README.md deleted file mode 100644 index d064c51..0000000 --- a/grpc-gcp/README.md +++ /dev/null @@ -1,117 +0,0 @@ -# gRPC-GCP for Node.js - -A Node.js module providing grpc supports for Google Cloud APIs. - -## Installation - -```sh -npm install grpc-gcp --save -``` - -## Usage - -Let's use Spanner API as an example. - -First, Create a json file defining API configuration, with ChannelPoolConfig and MethodConfig. - -```json -{ - "channelPool": { - "maxSize": 10, - "maxConcurrentStreamsLowWatermark": 1 - }, - "method": [ - { - "name": [ "/google.spanner.v1.Spanner/CreateSession" ], - "affinity": { - "command": "BIND", - "affinityKey": "name" - } - }, - { - "name": [ "/google.spanner.v1.Spanner/GetSession" ], - "affinity": { - "command": "BOUND", - "affinityKey": "name" - } - }, - { - "name": [ "/google.spanner.v1.Spanner/DeleteSession" ], - "affinity": { - "command": "UNBIND", - "affinityKey": "name" - } - } - ] -} -``` - -Load configuration to ApiConfig. - -```javascript -// @grpc/grpc-js can be used in place of grpc with no changes -var grpc = require('grpc'); -var grpcGcp = require('grpc-gcp')(grpc); -var fs = require('fs'); - -var apiDefinition = JSON.parse(fs.readFileSync('your_api_config_json_file')); -var apiConfig = grpcGcp.createGcpApiConfig(apiDefinition); -``` - -Pass `gcpChannelFactoryOverride` and `gcpCallInvocationTransformer` to channel options when initializing api client. - -```javascript -var channelOptions = { - channelFactoryOverride: grpcGcp.gcpChannelFactoryOverride, - callInvocationTransformer: grpcGcp.gcpCallInvocationTransformer, - gcpApiConfig: apiConfig, -}; - -var client = new SpannerClient( - 'spanner.googleapis.com:443', - channelCreds, - channelOptions -); -``` - -## Build from source - -Download source. - -```sh -git clone https://github.com/GoogleCloudPlatform/grpc-gcp-node.git && cd grpc-gcp-node -``` - -```sh -git submodule update --init --recursive -``` - -Build grpc-gcp. - -```sh -cd grpc-gcp -``` - -```sh -npm install -``` - -## Test - -Setup credentials. See [Getting Started With Authentication](https://cloud.google.com/docs/authentication/getting-started) for more details. - -```sh -export GOOGLE_APPLICATION_CREDENTIALS=path/to/key.json -``` - -Run unit tests. - -```sh -npm test -``` - -Run system tests. - -```sh -npm run system-test -``` diff --git a/grpc-gcp/package.json b/package.json similarity index 97% rename from grpc-gcp/package.json rename to package.json index 8486c16..cfc7087 100644 --- a/grpc-gcp/package.json +++ b/package.json @@ -7,7 +7,7 @@ "build": "tsc && cp -r src/generated build/src/", "system-test": "c8 mocha test/integration/*.js --reporter spec --timeout 10000", "test": "c8 mocha test/unit/*.js --reporter spec", - "lint": "gts check", + "lint": "gts check src/**/*.ts", "fix": "gts fix", "prepare": "npm run build" }, diff --git a/grpc-gcp/protos/grpc_gcp.proto b/protos/grpc_gcp.proto similarity index 100% rename from grpc-gcp/protos/grpc_gcp.proto rename to protos/grpc_gcp.proto diff --git a/grpc-gcp/protos/test_service.proto b/protos/test_service.proto similarity index 100% rename from grpc-gcp/protos/test_service.proto rename to protos/test_service.proto diff --git a/grpc-gcp/src/channel_ref.ts b/src/channel_ref.ts similarity index 100% rename from grpc-gcp/src/channel_ref.ts rename to src/channel_ref.ts diff --git a/grpc-gcp/src/gcp_channel_factory.ts b/src/gcp_channel_factory.ts similarity index 100% rename from grpc-gcp/src/gcp_channel_factory.ts rename to src/gcp_channel_factory.ts diff --git a/grpc-gcp/src/generated/grpc_gcp.d.ts b/src/generated/grpc_gcp.d.ts similarity index 100% rename from grpc-gcp/src/generated/grpc_gcp.d.ts rename to src/generated/grpc_gcp.d.ts diff --git a/grpc-gcp/src/generated/grpc_gcp.js b/src/generated/grpc_gcp.js similarity index 100% rename from grpc-gcp/src/generated/grpc_gcp.js rename to src/generated/grpc_gcp.js diff --git a/grpc-gcp/src/index.ts b/src/index.ts similarity index 100% rename from grpc-gcp/src/index.ts rename to src/index.ts diff --git a/grpc-gcp/test/.eslintrc.yaml b/test/.eslintrc.yaml similarity index 100% rename from grpc-gcp/test/.eslintrc.yaml rename to test/.eslintrc.yaml diff --git a/grpc-gcp/test/integration/local_service_test.js b/test/integration/local_service_test.js similarity index 100% rename from grpc-gcp/test/integration/local_service_test.js rename to test/integration/local_service_test.js diff --git a/grpc-gcp/test/integration/spanner.grpc.config b/test/integration/spanner.grpc.config similarity index 100% rename from grpc-gcp/test/integration/spanner.grpc.config rename to test/integration/spanner.grpc.config diff --git a/grpc-gcp/test/integration/spanner_test.js b/test/integration/spanner_test.js similarity index 100% rename from grpc-gcp/test/integration/spanner_test.js rename to test/integration/spanner_test.js diff --git a/grpc-gcp/test/unit/channel_factory_test.js b/test/unit/channel_factory_test.js similarity index 100% rename from grpc-gcp/test/unit/channel_factory_test.js rename to test/unit/channel_factory_test.js diff --git a/grpc-gcp/tsconfig.json b/tsconfig.json similarity index 100% rename from grpc-gcp/tsconfig.json rename to tsconfig.json From e28160cd0548e303b638fd0ff57bf7f7c31d7c33 Mon Sep 17 00:00:00 2001 From: Justin Beckwith Date: Mon, 3 May 2021 22:23:26 -0700 Subject: [PATCH 02/12] fixup system tests --- .kokoro/system-test.sh | 1 - .kokoro/test.sh | 1 - 2 files changed, 2 deletions(-) diff --git a/.kokoro/system-test.sh b/.kokoro/system-test.sh index a8aaec7..9146a49 100755 --- a/.kokoro/system-test.sh +++ b/.kokoro/system-test.sh @@ -23,7 +23,6 @@ export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/service-account.json export GCLOUD_PROJECT=long-door-651 cd $(dirname $0)/.. -cd grpc-gcp # Run a pre-test hook, if a pre-system-test.sh is in the project if [ -f .kokoro/pre-system-test.sh ]; then diff --git a/.kokoro/test.sh b/.kokoro/test.sh index 1223282..8d9c295 100755 --- a/.kokoro/test.sh +++ b/.kokoro/test.sh @@ -19,7 +19,6 @@ set -eo pipefail export NPM_CONFIG_PREFIX=/home/node/.npm-global cd $(dirname $0)/.. -cd grpc-gcp npm install # If tests are running against master, configure Build Cop From 09151ab6e7845eb940d1906165fb016654af1c25 Mon Sep 17 00:00:00 2001 From: Justin Beckwith Date: Mon, 3 May 2021 23:31:58 -0700 Subject: [PATCH 03/12] fix path --- test/integration/spanner_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/spanner_test.js b/test/integration/spanner_test.js index 474ebcd..71a5ac0 100644 --- a/test/integration/spanner_test.js +++ b/test/integration/spanner_test.js @@ -22,7 +22,7 @@ 'use strict'; -const PROTO_DIR = __dirname + '/../../../third_party/googleapis'; +const PROTO_DIR = __dirname + '../../third_party/googleapis'; const protoLoader = require('@grpc/proto-loader'); const assert = require('assert'); From 83e3856969681ef20c8cdfaabe8e8c314c9df4b7 Mon Sep 17 00:00:00 2001 From: Justin Beckwith Date: Mon, 3 May 2021 23:38:19 -0700 Subject: [PATCH 04/12] fix path --- test/integration/spanner_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/spanner_test.js b/test/integration/spanner_test.js index 71a5ac0..93b5d4d 100644 --- a/test/integration/spanner_test.js +++ b/test/integration/spanner_test.js @@ -22,7 +22,7 @@ 'use strict'; -const PROTO_DIR = __dirname + '../../third_party/googleapis'; +const PROTO_DIR = __dirname + '/../../third_party/googleapis'; const protoLoader = require('@grpc/proto-loader'); const assert = require('assert'); From dbf7103d214505a36806d0bbeff6f4a97e84b188 Mon Sep 17 00:00:00 2001 From: Justin Beckwith Date: Thu, 8 Jul 2021 12:56:27 -0700 Subject: [PATCH 05/12] no kokoro --- .kokoro/common.cfg | 24 ------- .kokoro/continuous/node10/common.cfg | 34 ---------- .kokoro/continuous/node10/docs.cfg | 4 -- .kokoro/continuous/node10/lint.cfg | 4 -- .kokoro/continuous/node10/samples-test.cfg | 7 -- .kokoro/continuous/node10/system-test.cfg | 7 -- .kokoro/continuous/node10/test.cfg | 9 --- .kokoro/continuous/node12/common.cfg | 24 ------- .kokoro/continuous/node12/test.cfg | 0 .kokoro/continuous/node8/common.cfg | 24 ------- .kokoro/continuous/node8/test.cfg | 0 .kokoro/docs.sh | 25 -------- .kokoro/lint.sh | 33 ---------- .kokoro/presubmit/node10/common.cfg | 34 ---------- .kokoro/presubmit/node10/docs.cfg | 4 -- .kokoro/presubmit/node10/lint.cfg | 4 -- .kokoro/presubmit/node10/samples-test.cfg | 7 -- .kokoro/presubmit/node10/system-test.cfg | 7 -- .kokoro/presubmit/node10/test.cfg | 0 .kokoro/presubmit/node12/common.cfg | 24 ------- .kokoro/presubmit/node12/test.cfg | 0 .kokoro/presubmit/node8/common.cfg | 24 ------- .kokoro/presubmit/node8/test.cfg | 0 .kokoro/presubmit/windows/common.cfg | 2 - .kokoro/presubmit/windows/test.cfg | 2 - .kokoro/publish.sh | 31 --------- .kokoro/release/docs.cfg | 26 -------- .kokoro/release/docs.sh | 50 --------------- .kokoro/release/publish.cfg | 74 ---------------------- .kokoro/samples-test.sh | 68 -------------------- .kokoro/system-test.sh | 62 ------------------ .kokoro/test.bat | 33 ---------- .kokoro/test.sh | 48 -------------- .kokoro/trampoline.sh | 27 -------- cloudbuild.yaml | 7 ++ 35 files changed, 7 insertions(+), 722 deletions(-) delete mode 100644 .kokoro/common.cfg delete mode 100644 .kokoro/continuous/node10/common.cfg delete mode 100644 .kokoro/continuous/node10/docs.cfg delete mode 100644 .kokoro/continuous/node10/lint.cfg delete mode 100644 .kokoro/continuous/node10/samples-test.cfg delete mode 100644 .kokoro/continuous/node10/system-test.cfg delete mode 100644 .kokoro/continuous/node10/test.cfg delete mode 100644 .kokoro/continuous/node12/common.cfg delete mode 100644 .kokoro/continuous/node12/test.cfg delete mode 100644 .kokoro/continuous/node8/common.cfg delete mode 100644 .kokoro/continuous/node8/test.cfg delete mode 100755 .kokoro/docs.sh delete mode 100755 .kokoro/lint.sh delete mode 100644 .kokoro/presubmit/node10/common.cfg delete mode 100644 .kokoro/presubmit/node10/docs.cfg delete mode 100644 .kokoro/presubmit/node10/lint.cfg delete mode 100644 .kokoro/presubmit/node10/samples-test.cfg delete mode 100644 .kokoro/presubmit/node10/system-test.cfg delete mode 100644 .kokoro/presubmit/node10/test.cfg delete mode 100644 .kokoro/presubmit/node12/common.cfg delete mode 100644 .kokoro/presubmit/node12/test.cfg delete mode 100644 .kokoro/presubmit/node8/common.cfg delete mode 100644 .kokoro/presubmit/node8/test.cfg delete mode 100644 .kokoro/presubmit/windows/common.cfg delete mode 100644 .kokoro/presubmit/windows/test.cfg delete mode 100755 .kokoro/publish.sh delete mode 100644 .kokoro/release/docs.cfg delete mode 100755 .kokoro/release/docs.sh delete mode 100644 .kokoro/release/publish.cfg delete mode 100755 .kokoro/samples-test.sh delete mode 100755 .kokoro/system-test.sh delete mode 100644 .kokoro/test.bat delete mode 100755 .kokoro/test.sh delete mode 100755 .kokoro/trampoline.sh create mode 100644 cloudbuild.yaml diff --git a/.kokoro/common.cfg b/.kokoro/common.cfg deleted file mode 100644 index 0cd9a47..0000000 --- a/.kokoro/common.cfg +++ /dev/null @@ -1,24 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Build logs will be here -action { - define_artifacts { - regex: "**/*sponge_log.xml" - } -} - -# Download trampoline resources. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" - -# Use the trampoline script to run in docker. -build_file: "grpc-gcp-node/.kokoro/trampoline.sh" - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/node:10-user" -} -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/test.sh" -} diff --git a/.kokoro/continuous/node10/common.cfg b/.kokoro/continuous/node10/common.cfg deleted file mode 100644 index 0a49b7c..0000000 --- a/.kokoro/continuous/node10/common.cfg +++ /dev/null @@ -1,34 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Build logs will be here -action { - define_artifacts { - regex: "**/*sponge_log.xml" - } -} - -# Bring in codecov.io master token into the build as $KOKORO_KEYSTORE_DIR/73713_dpebot_codecov_token -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "dpebot_codecov_token" - } - } -} - -# Download trampoline resources. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" - -# Use the trampoline script to run in docker. -build_file: "grpc-gcp-node/.kokoro/trampoline.sh" - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/node:10-user" -} -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/test.sh" -} diff --git a/.kokoro/continuous/node10/docs.cfg b/.kokoro/continuous/node10/docs.cfg deleted file mode 100644 index 08510b8..0000000 --- a/.kokoro/continuous/node10/docs.cfg +++ /dev/null @@ -1,4 +0,0 @@ -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/docs.sh" -} diff --git a/.kokoro/continuous/node10/lint.cfg b/.kokoro/continuous/node10/lint.cfg deleted file mode 100644 index 5a02a06..0000000 --- a/.kokoro/continuous/node10/lint.cfg +++ /dev/null @@ -1,4 +0,0 @@ -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/lint.sh" -} diff --git a/.kokoro/continuous/node10/samples-test.cfg b/.kokoro/continuous/node10/samples-test.cfg deleted file mode 100644 index 67eed17..0000000 --- a/.kokoro/continuous/node10/samples-test.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# Download resources for system tests (service account key, etc.) -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs" - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/samples-test.sh" -} diff --git a/.kokoro/continuous/node10/system-test.cfg b/.kokoro/continuous/node10/system-test.cfg deleted file mode 100644 index 62cff17..0000000 --- a/.kokoro/continuous/node10/system-test.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# Download resources for system tests (service account key, etc.) -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs" - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/system-test.sh" -} diff --git a/.kokoro/continuous/node10/test.cfg b/.kokoro/continuous/node10/test.cfg deleted file mode 100644 index 468b8c7..0000000 --- a/.kokoro/continuous/node10/test.cfg +++ /dev/null @@ -1,9 +0,0 @@ -# Bring in codecov.io master token into the build as $KOKORO_KEYSTORE_DIR/73713_dpebot_codecov_token -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "dpebot_codecov_token" - } - } -} diff --git a/.kokoro/continuous/node12/common.cfg b/.kokoro/continuous/node12/common.cfg deleted file mode 100644 index 984e544..0000000 --- a/.kokoro/continuous/node12/common.cfg +++ /dev/null @@ -1,24 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Build logs will be here -action { - define_artifacts { - regex: "**/*sponge_log.xml" - } -} - -# Download trampoline resources. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" - -# Use the trampoline script to run in docker. -build_file: "grpc-gcp-node/.kokoro/trampoline.sh" - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/node:12-user" -} -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/test.sh" -} diff --git a/.kokoro/continuous/node12/test.cfg b/.kokoro/continuous/node12/test.cfg deleted file mode 100644 index e69de29..0000000 diff --git a/.kokoro/continuous/node8/common.cfg b/.kokoro/continuous/node8/common.cfg deleted file mode 100644 index 7966d25..0000000 --- a/.kokoro/continuous/node8/common.cfg +++ /dev/null @@ -1,24 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Build logs will be here -action { - define_artifacts { - regex: "**/*sponge_log.xml" - } -} - -# Download trampoline resources. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" - -# Use the trampoline script to run in docker. -build_file: "grpc-gcp-node/.kokoro/trampoline.sh" - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/node:8-user" -} -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/test.sh" -} diff --git a/.kokoro/continuous/node8/test.cfg b/.kokoro/continuous/node8/test.cfg deleted file mode 100644 index e69de29..0000000 diff --git a/.kokoro/docs.sh b/.kokoro/docs.sh deleted file mode 100755 index 952403f..0000000 --- a/.kokoro/docs.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -# Copyright 2018 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 -# -# https://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 - -export NPM_CONFIG_PREFIX=/home/node/.npm-global - -cd $(dirname $0)/.. - -npm install - -npm run docs-test diff --git a/.kokoro/lint.sh b/.kokoro/lint.sh deleted file mode 100755 index b03cb04..0000000 --- a/.kokoro/lint.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# Copyright 2018 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 -# -# https://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 - -export NPM_CONFIG_PREFIX=/home/node/.npm-global - -cd $(dirname $0)/.. - -npm install - -# Install and link samples -if [ -f samples/package.json ]; then - cd samples/ - npm link ../ - npm install - cd .. -fi - -npm run lint diff --git a/.kokoro/presubmit/node10/common.cfg b/.kokoro/presubmit/node10/common.cfg deleted file mode 100644 index 0a49b7c..0000000 --- a/.kokoro/presubmit/node10/common.cfg +++ /dev/null @@ -1,34 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Build logs will be here -action { - define_artifacts { - regex: "**/*sponge_log.xml" - } -} - -# Bring in codecov.io master token into the build as $KOKORO_KEYSTORE_DIR/73713_dpebot_codecov_token -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "dpebot_codecov_token" - } - } -} - -# Download trampoline resources. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" - -# Use the trampoline script to run in docker. -build_file: "grpc-gcp-node/.kokoro/trampoline.sh" - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/node:10-user" -} -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/test.sh" -} diff --git a/.kokoro/presubmit/node10/docs.cfg b/.kokoro/presubmit/node10/docs.cfg deleted file mode 100644 index 08510b8..0000000 --- a/.kokoro/presubmit/node10/docs.cfg +++ /dev/null @@ -1,4 +0,0 @@ -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/docs.sh" -} diff --git a/.kokoro/presubmit/node10/lint.cfg b/.kokoro/presubmit/node10/lint.cfg deleted file mode 100644 index 5a02a06..0000000 --- a/.kokoro/presubmit/node10/lint.cfg +++ /dev/null @@ -1,4 +0,0 @@ -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/lint.sh" -} diff --git a/.kokoro/presubmit/node10/samples-test.cfg b/.kokoro/presubmit/node10/samples-test.cfg deleted file mode 100644 index 67eed17..0000000 --- a/.kokoro/presubmit/node10/samples-test.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# Download resources for system tests (service account key, etc.) -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs" - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/samples-test.sh" -} diff --git a/.kokoro/presubmit/node10/system-test.cfg b/.kokoro/presubmit/node10/system-test.cfg deleted file mode 100644 index 62cff17..0000000 --- a/.kokoro/presubmit/node10/system-test.cfg +++ /dev/null @@ -1,7 +0,0 @@ -# Download resources for system tests (service account key, etc.) -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/google-cloud-nodejs" - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/system-test.sh" -} diff --git a/.kokoro/presubmit/node10/test.cfg b/.kokoro/presubmit/node10/test.cfg deleted file mode 100644 index e69de29..0000000 diff --git a/.kokoro/presubmit/node12/common.cfg b/.kokoro/presubmit/node12/common.cfg deleted file mode 100644 index 984e544..0000000 --- a/.kokoro/presubmit/node12/common.cfg +++ /dev/null @@ -1,24 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Build logs will be here -action { - define_artifacts { - regex: "**/*sponge_log.xml" - } -} - -# Download trampoline resources. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" - -# Use the trampoline script to run in docker. -build_file: "grpc-gcp-node/.kokoro/trampoline.sh" - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/node:12-user" -} -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/test.sh" -} diff --git a/.kokoro/presubmit/node12/test.cfg b/.kokoro/presubmit/node12/test.cfg deleted file mode 100644 index e69de29..0000000 diff --git a/.kokoro/presubmit/node8/common.cfg b/.kokoro/presubmit/node8/common.cfg deleted file mode 100644 index 7966d25..0000000 --- a/.kokoro/presubmit/node8/common.cfg +++ /dev/null @@ -1,24 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - -# Build logs will be here -action { - define_artifacts { - regex: "**/*sponge_log.xml" - } -} - -# Download trampoline resources. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" - -# Use the trampoline script to run in docker. -build_file: "grpc-gcp-node/.kokoro/trampoline.sh" - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/node:8-user" -} -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/test.sh" -} diff --git a/.kokoro/presubmit/node8/test.cfg b/.kokoro/presubmit/node8/test.cfg deleted file mode 100644 index e69de29..0000000 diff --git a/.kokoro/presubmit/windows/common.cfg b/.kokoro/presubmit/windows/common.cfg deleted file mode 100644 index d6e25e0..0000000 --- a/.kokoro/presubmit/windows/common.cfg +++ /dev/null @@ -1,2 +0,0 @@ -# Format: //devtools/kokoro/config/proto/build.proto - diff --git a/.kokoro/presubmit/windows/test.cfg b/.kokoro/presubmit/windows/test.cfg deleted file mode 100644 index 4e7db2e..0000000 --- a/.kokoro/presubmit/windows/test.cfg +++ /dev/null @@ -1,2 +0,0 @@ -# Use the test file directly -build_file: "grpc-gcp-node/.kokoro/test.bat" diff --git a/.kokoro/publish.sh b/.kokoro/publish.sh deleted file mode 100755 index 0867180..0000000 --- a/.kokoro/publish.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -# Copyright 2018 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 -# -# https://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 - -export NPM_CONFIG_PREFIX=/home/node/.npm-global - -# Start the releasetool reporter -python3 -m pip install gcp-releasetool -python3 -m releasetool publish-reporter-script > /tmp/publisher-script; source /tmp/publisher-script - -cd $(dirname $0)/.. - -NPM_TOKEN=$(cat $KOKORO_KEYSTORE_DIR/73713_grpc-gcp-npm-token) -echo "//wombat-dressing-room.appspot.com/:_authToken=${NPM_TOKEN}" > ~/.npmrc - -npm install -npm publish --access=public --registry=https://wombat-dressing-room.appspot.com diff --git a/.kokoro/release/docs.cfg b/.kokoro/release/docs.cfg deleted file mode 100644 index 255553c..0000000 --- a/.kokoro/release/docs.cfg +++ /dev/null @@ -1,26 +0,0 @@ -# service account used to publish up-to-date docs. -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "docuploader_service_account" - } - } -} - -# doc publications use a Python image. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/node:10-user" -} - -# Download trampoline resources. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" - -# Use the trampoline script to run in docker. -build_file: "grpc-gcp-node/.kokoro/trampoline.sh" - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/release/docs.sh" -} diff --git a/.kokoro/release/docs.sh b/.kokoro/release/docs.sh deleted file mode 100755 index 4d3a086..0000000 --- a/.kokoro/release/docs.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -# Copyright 2019 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 -# -# https://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 - -# build jsdocs (Python is installed on the Node 10 docker image). -if [[ -z "$CREDENTIALS" ]]; then - # if CREDENTIALS are explicitly set, assume we're testing locally - # and don't set NPM_CONFIG_PREFIX. - export NPM_CONFIG_PREFIX=/home/node/.npm-global - export PATH="$PATH:/home/node/.npm-global/bin" - cd $(dirname $0)/../.. -fi -npm install -npm run docs - -# create docs.metadata, based on package.json and .repo-metadata.json. -npm i json@9.0.6 -g -python3 -m pip install --user gcp-docuploader -python3 -m docuploader create-metadata \ - --name=$(cat .repo-metadata.json | json name) \ - --version=$(cat package.json | json version) \ - --language=$(cat .repo-metadata.json | json language) \ - --distribution-name=$(cat .repo-metadata.json | json distribution_name) \ - --product-page=$(cat .repo-metadata.json | json product_documentation) \ - --github-repository=$(cat .repo-metadata.json | json repo) \ - --issue-tracker=$(cat .repo-metadata.json | json issue_tracker) -cp docs.metadata ./docs/docs.metadata - -# deploy the docs. -if [[ -z "$CREDENTIALS" ]]; then - CREDENTIALS=${KOKORO_KEYSTORE_DIR}/73713_docuploader_service_account -fi -if [[ -z "$BUCKET" ]]; then - BUCKET=docs-staging -fi -python3 -m docuploader upload ./docs --credentials $CREDENTIALS --staging-bucket $BUCKET diff --git a/.kokoro/release/publish.cfg b/.kokoro/release/publish.cfg deleted file mode 100644 index c56fecd..0000000 --- a/.kokoro/release/publish.cfg +++ /dev/null @@ -1,74 +0,0 @@ -# Get npm token from Keystore -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "google_cloud_npm_token" - backend_type: FASTCONFIGPUSH - } - } -} - -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "yoshi-automation-github-key" - } - } -} - -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "docuploader_service_account" - } - } -} - -# Fetch magictoken to use with Magic Github Proxy -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "releasetool-magictoken" - } - } -} - -# Fetch api key to use with Magic Github Proxy -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "magic-github-proxy-api-key" - } - } -} - -before_action { - fetch_keystore { - keystore_resource { - keystore_config_id: 73713 - keyname: "grpc-gcp-npm-token" - } - } -} - -# Download trampoline resources. -gfile_resources: "/bigstore/cloud-devrel-kokoro-resources/trampoline" - -# Use the trampoline script to run in docker. -build_file: "grpc-gcp-node/.kokoro/trampoline.sh" - -# Configure the docker image for kokoro-trampoline. -env_vars: { - key: "TRAMPOLINE_IMAGE" - value: "gcr.io/cloud-devrel-kokoro-resources/node:8-user" -} - -env_vars: { - key: "TRAMPOLINE_BUILD_FILE" - value: "github/grpc-gcp-node/.kokoro/publish.sh" -} diff --git a/.kokoro/samples-test.sh b/.kokoro/samples-test.sh deleted file mode 100755 index 86e83c9..0000000 --- a/.kokoro/samples-test.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/bash - -# Copyright 2018 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 -# -# https://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 - -export NPM_CONFIG_PREFIX=/home/node/.npm-global - -# Setup service account credentials. -export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/service-account.json -export GCLOUD_PROJECT=long-door-651 - -cd $(dirname $0)/.. - -# Run a pre-test hook, if a pre-samples-test.sh is in the project -if [ -f .kokoro/pre-samples-test.sh ]; then - set +x - . .kokoro/pre-samples-test.sh - set -x -fi - -if [ -f samples/package.json ]; then - npm install - - # Install and link samples - cd samples/ - npm link ../ - npm install - cd .. - # If tests are running against master, configure Build Cop - # to open issues on failures: - if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]]; then - export MOCHA_REPORTER_OUTPUT=test_output_sponge_log.xml - export MOCHA_REPORTER=xunit - cleanup() { - chmod +x $KOKORO_GFILE_DIR/linux_amd64/buildcop - $KOKORO_GFILE_DIR/linux_amd64/buildcop - } - trap cleanup EXIT HUP - fi - - npm run samples-test -fi - -# codecov combines coverage across integration and unit tests. Include -# the logic below for any environment you wish to collect coverage for: -COVERAGE_NODE=10 -if npx check-node-version@3.3.0 --silent --node $COVERAGE_NODE; then - NYC_BIN=./node_modules/nyc/bin/nyc.js - if [ -f "$NYC_BIN" ]; then - $NYC_BIN report || true - fi - bash $KOKORO_GFILE_DIR/codecov.sh -else - echo "coverage is only reported for Node $COVERAGE_NODE" -fi diff --git a/.kokoro/system-test.sh b/.kokoro/system-test.sh deleted file mode 100755 index 9146a49..0000000 --- a/.kokoro/system-test.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash - -# Copyright 2018 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 -# -# https://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 - -export NPM_CONFIG_PREFIX=/home/node/.npm-global - -# Setup service account credentials. -export GOOGLE_APPLICATION_CREDENTIALS=${KOKORO_GFILE_DIR}/service-account.json -export GCLOUD_PROJECT=long-door-651 - -cd $(dirname $0)/.. - -# Run a pre-test hook, if a pre-system-test.sh is in the project -if [ -f .kokoro/pre-system-test.sh ]; then - set +x - . .kokoro/pre-system-test.sh - set -x -fi - -git submodule update --init --recursive -npm install - -# If tests are running against master, configure Build Cop -# to open issues on failures: -if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]]; then - export MOCHA_REPORTER_OUTPUT=test_output_sponge_log.xml - export MOCHA_REPORTER=xunit - cleanup() { - chmod +x $KOKORO_GFILE_DIR/linux_amd64/buildcop - $KOKORO_GFILE_DIR/linux_amd64/buildcop - } - trap cleanup EXIT HUP -fi - -npm run system-test - -# codecov combines coverage across integration and unit tests. Include -# the logic below for any environment you wish to collect coverage for: -COVERAGE_NODE=10 -if npx check-node-version@3.3.0 --silent --node $COVERAGE_NODE; then - NYC_BIN=./node_modules/nyc/bin/nyc.js - if [ -f "$NYC_BIN" ]; then - $NYC_BIN report || true - fi - bash $KOKORO_GFILE_DIR/codecov.sh -else - echo "coverage is only reported for Node $COVERAGE_NODE" -fi diff --git a/.kokoro/test.bat b/.kokoro/test.bat deleted file mode 100644 index ae59e59..0000000 --- a/.kokoro/test.bat +++ /dev/null @@ -1,33 +0,0 @@ -@rem Copyright 2018 Google LLC. All rights reserved. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem http://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. - -@echo "Starting Windows build" - -cd /d %~dp0 -cd .. - -@rem npm path is not currently set in our image, we should fix this next time -@rem we upgrade Node.js in the image: -SET PATH=%PATH%;/cygdrive/c/Program Files/nodejs/npm - -call nvm use v12.14.1 -call which node - -call npm install || goto :error -call npm run test || goto :error - -goto :EOF - -:error -exit /b 1 diff --git a/.kokoro/test.sh b/.kokoro/test.sh deleted file mode 100755 index 8d9c295..0000000 --- a/.kokoro/test.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash - -# Copyright 2018 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 -# -# https://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 - -export NPM_CONFIG_PREFIX=/home/node/.npm-global - -cd $(dirname $0)/.. - -npm install -# If tests are running against master, configure Build Cop -# to open issues on failures: -if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]]; then - export MOCHA_REPORTER_OUTPUT=test_output_sponge_log.xml - export MOCHA_REPORTER=xunit - cleanup() { - chmod +x $KOKORO_GFILE_DIR/linux_amd64/buildcop - $KOKORO_GFILE_DIR/linux_amd64/buildcop - } - trap cleanup EXIT HUP -fi -npm test - -# codecov combines coverage across integration and unit tests. Include -# the logic below for any environment you wish to collect coverage for: -COVERAGE_NODE=10 -if npx check-node-version@3.3.0 --silent --node $COVERAGE_NODE; then - NYC_BIN=./node_modules/nyc/bin/nyc.js - if [ -f "$NYC_BIN" ]; then - $NYC_BIN report || true - fi - bash $KOKORO_GFILE_DIR/codecov.sh -else - echo "coverage is only reported for Node $COVERAGE_NODE" -fi diff --git a/.kokoro/trampoline.sh b/.kokoro/trampoline.sh deleted file mode 100755 index 9bd4905..0000000 --- a/.kokoro/trampoline.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -# Copyright 2017 Google Inc. -# -# 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 - -# Always run the cleanup script, regardless of the success of bouncing into -# the container. -function cleanup() { - chmod +x ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh - ${KOKORO_GFILE_DIR}/trampoline_cleanup.sh - echo "cleanup"; -} -trap cleanup EXIT - -python3 "${KOKORO_GFILE_DIR}/trampoline_v1.py" diff --git a/cloudbuild.yaml b/cloudbuild.yaml new file mode 100644 index 0000000..9f9c69a --- /dev/null +++ b/cloudbuild.yaml @@ -0,0 +1,7 @@ +steps: +- name: node:14 + entrypoint: npm + args: ['install', '--unsafe-perm'] +- name: node:14 + entrypoint: npm + args: ['run', 'system-test'] From 1393ebdba9db6a963df2e90b0dc19b2c7cf1e1ad Mon Sep 17 00:00:00 2001 From: Justin Beckwith Date: Thu, 8 Jul 2021 13:30:46 -0700 Subject: [PATCH 06/12] submodule update --- cloudbuild.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cloudbuild.yaml b/cloudbuild.yaml index 9f9c69a..34b1b43 100644 --- a/cloudbuild.yaml +++ b/cloudbuild.yaml @@ -1,4 +1,7 @@ steps: +- name: node:14 + entrypoint: git + args: ['submodule', 'update', '--init', '--recursive'] - name: node:14 entrypoint: npm args: ['install', '--unsafe-perm'] From 7de460822dcf8b7f5e60a46a9be073582cae824d Mon Sep 17 00:00:00 2001 From: Justin Beckwith Date: Thu, 8 Jul 2021 13:43:43 -0700 Subject: [PATCH 07/12] uncally --- test/integration/spanner_test.js | 59 +++++++++++++++----------------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/test/integration/spanner_test.js b/test/integration/spanner_test.js index 93b5d4d..4c9de33 100644 --- a/test/integration/spanner_test.js +++ b/test/integration/spanner_test.js @@ -53,40 +53,35 @@ for (const grpcLibName of ['grpc', '@grpc/grpc-js']) { let client; let pool; - beforeEach(done => { + beforeEach(async () => { const authFactory = new GoogleAuth(); - authFactory.getApplicationDefault((err, auth) => { - assert.ifError(err); - - const scopes = [_OAUTH_SCOPE]; - auth = auth.createScoped(scopes); - - const sslCreds = grpc.credentials.createSsl(); - const callCreds = grpc.credentials.createFromGoogleCredential(auth); - const channelCreds = grpc.credentials.combineChannelCredentials( - sslCreds, - callCreds - ); - - const apiDefinition = JSON.parse(fs.readFileSync(_CONFIG_FILE)); - const apiConfig = grpcGcp.createGcpApiConfig(apiDefinition); - - const channelOptions = { - channelFactoryOverride: grpcGcp.gcpChannelFactoryOverride, - callInvocationTransformer: grpcGcp.gcpCallInvocationTransformer, - gcpApiConfig: apiConfig, - }; - - client = new spannerGrpc.google.spanner.v1.Spanner( - _TARGET, - channelCreds, - channelOptions - ); - - pool = client.getChannel(); - - done(); + const auth = await authFactory.getClient({ + scopes: [_OAUTH_SCOPE], }); + + const sslCreds = grpc.credentials.createSsl(); + const callCreds = grpc.credentials.createFromGoogleCredential(auth); + const channelCreds = grpc.credentials.combineChannelCredentials( + sslCreds, + callCreds + ); + + const apiDefinition = JSON.parse(fs.readFileSync(_CONFIG_FILE)); + const apiConfig = grpcGcp.createGcpApiConfig(apiDefinition); + + const channelOptions = { + channelFactoryOverride: grpcGcp.gcpChannelFactoryOverride, + callInvocationTransformer: grpcGcp.gcpCallInvocationTransformer, + gcpApiConfig: apiConfig, + }; + + client = new spannerGrpc.google.spanner.v1.Spanner( + _TARGET, + channelCreds, + channelOptions + ); + + pool = client.getChannel(); }); it('Test session operations', done => { From 2e8add2c537e149faa48de570449bdb2ad024497 Mon Sep 17 00:00:00 2001 From: Justin Beckwith Date: Thu, 8 Jul 2021 13:47:32 -0700 Subject: [PATCH 08/12] uncally --- test/integration/spanner_test.js | 50 ++++++++++++++------------------ 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/test/integration/spanner_test.js b/test/integration/spanner_test.js index 4c9de33..bb63de8 100644 --- a/test/integration/spanner_test.js +++ b/test/integration/spanner_test.js @@ -54,10 +54,10 @@ for (const grpcLibName of ['grpc', '@grpc/grpc-js']) { let pool; beforeEach(async () => { - const authFactory = new GoogleAuth(); - const auth = await authFactory.getClient({ + const authFactory = new GoogleAuth({ scopes: [_OAUTH_SCOPE], }); + const auth = await authFactory.getClient(); const sslCreds = grpc.credentials.createSsl(); const callCreds = grpc.credentials.createFromGoogleCredential(auth); @@ -318,36 +318,30 @@ for (const grpcLibName of ['grpc', '@grpc/grpc-js']) { let client; let pool; - beforeEach(done => { - const authFactory = new GoogleAuth(); - authFactory.getApplicationDefault((err, auth) => { - assert.ifError(err); - - const scopes = [_OAUTH_SCOPE]; - auth = auth.createScoped(scopes); - - const sslCreds = grpc.credentials.createSsl(); - const callCreds = grpc.credentials.createFromGoogleCredential(auth); - const channelCreds = grpc.credentials.combineChannelCredentials( - sslCreds, - callCreds - ); - - const apiDefinition = JSON.parse(fs.readFileSync(_CONFIG_FILE)); - const apiConfig = grpcGcp.createGcpApiConfig(apiDefinition); + beforeEach(async () => { + const authFactory = new GoogleAuth({ + scopes: [_OAUTH_SCOPE], + }); + const auth = await authFactory.getClient(); - const channelOptions = { - channelFactoryOverride: grpcGcp.gcpChannelFactoryOverride, - callInvocationTransformer: grpcGcp.gcpCallInvocationTransformer, - gcpApiConfig: apiConfig, - }; + const sslCreds = grpc.credentials.createSsl(); + const callCreds = grpc.credentials.createFromGoogleCredential(auth); + const channelCreds = grpc.credentials.combineChannelCredentials( + sslCreds, + callCreds + ); - client = new SpannerClient(_TARGET, channelCreds, channelOptions); + const apiDefinition = JSON.parse(fs.readFileSync(_CONFIG_FILE)); + const apiConfig = grpcGcp.createGcpApiConfig(apiDefinition); - pool = client.getChannel(); + const channelOptions = { + channelFactoryOverride: grpcGcp.gcpChannelFactoryOverride, + callInvocationTransformer: grpcGcp.gcpCallInvocationTransformer, + gcpApiConfig: apiConfig, + }; - done(); - }); + client = new SpannerClient(_TARGET, channelCreds, channelOptions); + pool = client.getChannel(); }); it('Test session operations', done => { From 7bc131eefa42062b3aae11a4ad9acd2f62b2cc2d Mon Sep 17 00:00:00 2001 From: Justin Beckwith Date: Thu, 8 Jul 2021 14:22:24 -0700 Subject: [PATCH 09/12] use a different project --- test/integration/spanner_test.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/integration/spanner_test.js b/test/integration/spanner_test.js index bb63de8..b0ceafe 100644 --- a/test/integration/spanner_test.js +++ b/test/integration/spanner_test.js @@ -32,7 +32,7 @@ const gax = require('google-gax'); const _TARGET = 'spanner.googleapis.com:443'; const _OAUTH_SCOPE = 'https://www.googleapis.com/auth/cloud-platform'; -const _DATABASE = 'projects/grpc-gcp/instances/sample/databases/benchmark'; +const _DATABASE = 'projects/long-door-651/instances/sample/databases/benchmark'; const _TEST_SQL = 'select id from storage'; const _CONFIG_FILE = __dirname + '/spanner.grpc.config'; @@ -54,9 +54,7 @@ for (const grpcLibName of ['grpc', '@grpc/grpc-js']) { let pool; beforeEach(async () => { - const authFactory = new GoogleAuth({ - scopes: [_OAUTH_SCOPE], - }); + const authFactory = new GoogleAuth(); const auth = await authFactory.getClient(); const sslCreds = grpc.credentials.createSsl(); From ce61920dcfe360f7597dfa46c8438f166d2383bd Mon Sep 17 00:00:00 2001 From: WhiteSource Renovate Date: Tue, 13 Jul 2021 20:00:04 +0200 Subject: [PATCH 10/12] chore(deps): update dependency google-auth-library to v7.3.0 (#110) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cfc7087..bf9581e 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "devDependencies": { "@grpc/proto-loader": "0.6.2", "c8": "7.7.2", - "google-auth-library": "7.1.0", + "google-auth-library": "7.3.0", "google-gax": "2.14.1", "google-protobuf": "3.17.1", "grpc": "1.24.10", From c6aec1d0b098acb92584ba725a9f662c9c369196 Mon Sep 17 00:00:00 2001 From: Yuri Golobokov Date: Wed, 14 Jul 2021 13:46:16 -0700 Subject: [PATCH 11/12] Creating and deleting test DB in Spanner integration tests. --- package.json | 1 + test/integration/spanner_test.js | 706 +++++++++++++++++-------------- 2 files changed, 388 insertions(+), 319 deletions(-) diff --git a/package.json b/package.json index bf9581e..8f9bb93 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ }, "devDependencies": { "@grpc/proto-loader": "0.6.2", + "@google-cloud/spanner": "^5.12.0", "c8": "7.7.2", "google-auth-library": "7.3.0", "google-gax": "2.14.1", diff --git a/test/integration/spanner_test.js b/test/integration/spanner_test.js index b0ceafe..94d35af 100644 --- a/test/integration/spanner_test.js +++ b/test/integration/spanner_test.js @@ -29,422 +29,490 @@ const assert = require('assert'); const {GoogleAuth} = require('google-auth-library'); const fs = require('fs'); const gax = require('google-gax'); +const {Spanner} = require('@google-cloud/spanner'); const _TARGET = 'spanner.googleapis.com:443'; const _OAUTH_SCOPE = 'https://www.googleapis.com/auth/cloud-platform'; -const _DATABASE = 'projects/long-door-651/instances/sample/databases/benchmark'; -const _TEST_SQL = 'select id from storage'; -const _CONFIG_FILE = __dirname + '/spanner.grpc.config'; +const _MAX_RAND_ID = 1000000; +const _PROJECT_ID = 'long-door-651'; +const _INSTANCE_ID = + 'test-instance-' + Math.floor(Math.random() * _MAX_RAND_ID); +const _DATABASE_ID = 'test-db-' + Math.floor(Math.random() * _MAX_RAND_ID); +const _TABLE_NAME = 'storage'; +const _DATABASE = + `projects/${_PROJECT_ID}/instances/${_INSTANCE_ID}/databases/${_DATABASE_ID}`; +const _TEST_SQL = `select id from ${_TABLE_NAME}`; +const _CONFIG_FILE = `${__dirname}/spanner.grpc.config`; const getGrpcGcpObjects = require('../../build/src'); -for (const grpcLibName of ['grpc', '@grpc/grpc-js']) { - describe('Using ' + grpcLibName, () => { - const grpc = require(grpcLibName); - const grpcGcp = getGrpcGcpObjects(grpc); - describe('Spanner integration tests', () => { - describe('SpannerClient generated by jspb', () => { - const spannerPackageDef = protoLoader.loadSync( - PROTO_DIR + '/google/spanner/v1/spanner.proto', - {includeDirs: [PROTO_DIR]} - ); - const spannerGrpc = grpc.loadPackageDefinition(spannerPackageDef); - - let client; - let pool; - - beforeEach(async () => { - const authFactory = new GoogleAuth(); - const auth = await authFactory.getClient(); - - const sslCreds = grpc.credentials.createSsl(); - const callCreds = grpc.credentials.createFromGoogleCredential(auth); - const channelCreds = grpc.credentials.combineChannelCredentials( - sslCreds, - callCreds - ); +const spanner = new Spanner({projectId: _PROJECT_ID}); +const instance = spanner.instance(_INSTANCE_ID); + +describe("Spanner integration tests", () => { + + before(async function() { + this.timeout(60000); + // Create test instance. + console.log(`Creating instance ${instance.formattedName_}.`); + const [, instOp] = await instance.create({ + config: 'regional-us-central1', + nodes: 1, + displayName: 'grpc-gcp-node tests', + labels: { + ['grpc_gcp_node_tests']: 'true', + created: Math.round(Date.now() / 1000).toString(), // current time + }, + }); + + console.log(`Waiting for operation on ${instance.id} to complete...`); + await instOp.promise(); + console.log(`Created instance ${_INSTANCE_ID}.`); + + // Create test database. + const [database, dbOp] = await instance.createDatabase(_DATABASE_ID); + + console.log(`Waiting for operation on ${database.id} to complete...`); + await dbOp.promise(); + + console.log(`Created database ${_DATABASE_ID} on instance ${_INSTANCE_ID}.`); + + // Create test table. + const table = database.table(_TABLE_NAME); + const schema = + `CREATE TABLE ${_TABLE_NAME} (id STRING(1024)) PRIMARY KEY(id)`; + + const [, tableOp] = await table.create(schema); + console.log(`Waiting for operation on ${table.id} to complete...`); + await tableOp.promise(); + console.log(`Created table "${_TABLE_NAME}".`); - const apiDefinition = JSON.parse(fs.readFileSync(_CONFIG_FILE)); - const apiConfig = grpcGcp.createGcpApiConfig(apiDefinition); + // Populate test table. + const row = { + id: 'payload', + }; - const channelOptions = { - channelFactoryOverride: grpcGcp.gcpChannelFactoryOverride, - callInvocationTransformer: grpcGcp.gcpCallInvocationTransformer, - gcpApiConfig: apiConfig, - }; + console.log(`Inserting row to the table...`); + await table.insert(row); + console.log(`Row inserted into table "${_TABLE_NAME}".`); + }); + + after(async function() { + this.timeout(60000); + // Delete test instance. + console.log(`Deleting instance ${instance.id}...`); + await instance.delete(); + console.log(`Deleted instance ${_INSTANCE_ID}.`); + }); - client = new spannerGrpc.google.spanner.v1.Spanner( - _TARGET, - channelCreds, - channelOptions + for (const grpcLibName of ['grpc', '@grpc/grpc-js']) { + describe('Using ' + grpcLibName, () => { + const grpc = require(grpcLibName); + const grpcGcp = getGrpcGcpObjects(grpc); + describe('Spanner integration tests', () => { + describe('SpannerClient generated by jspb', () => { + const spannerPackageDef = protoLoader.loadSync( + PROTO_DIR + '/google/spanner/v1/spanner.proto', + {includeDirs: [PROTO_DIR]} ); + const spannerGrpc = grpc.loadPackageDefinition(spannerPackageDef); - pool = client.getChannel(); - }); + let client; + let pool; - it('Test session operations', done => { - const createSessionRequest = {database: _DATABASE}; - client.createSession(createSessionRequest, (err, session) => { - assert.ifError(err); - const sessionName = session.name; + beforeEach(async () => { + const authFactory = new GoogleAuth(); + const auth = await authFactory.getClient(); - const getSessionRequest = {name: sessionName}; - client.getSession(getSessionRequest, (err, sessionResult) => { + const sslCreds = grpc.credentials.createSsl(); + const callCreds = grpc.credentials.createFromGoogleCredential(auth); + const channelCreds = grpc.credentials.combineChannelCredentials( + sslCreds, + callCreds + ); + + const apiDefinition = JSON.parse(fs.readFileSync(_CONFIG_FILE)); + const apiConfig = grpcGcp.createGcpApiConfig(apiDefinition); + + const channelOptions = { + channelFactoryOverride: grpcGcp.gcpChannelFactoryOverride, + callInvocationTransformer: grpcGcp.gcpCallInvocationTransformer, + gcpApiConfig: apiConfig, + }; + + client = new spannerGrpc.google.spanner.v1.Spanner( + _TARGET, + channelCreds, + channelOptions + ); + + pool = client.getChannel(); + }); + + it('Test session operations', done => { + const createSessionRequest = {database: _DATABASE}; + client.createSession(createSessionRequest, (err, session) => { assert.ifError(err); - assert.strictEqual(sessionResult.name, sessionName); + const sessionName = session.name; - const listSessionsRequest = {database: _DATABASE}; - client.listSessions(listSessionsRequest, (err, response) => { + const getSessionRequest = {name: sessionName}; + client.getSession(getSessionRequest, (err, sessionResult) => { assert.ifError(err); - const sessionsList = response.sessions; - const sessionNames = sessionsList.map(session => session.name); - assert(sessionNames.includes(sessionName)); + assert.strictEqual(sessionResult.name, sessionName); - const deleteSessionRequest = {name: sessionName}; - client.deleteSession(deleteSessionRequest, err => { + const listSessionsRequest = {database: _DATABASE}; + client.listSessions(listSessionsRequest, (err, response) => { assert.ifError(err); - done(); + const sessionsList = response.sessions; + const sessionNames = sessionsList.map(session => session.name); + assert(sessionNames.includes(sessionName)); + + const deleteSessionRequest = {name: sessionName}; + client.deleteSession(deleteSessionRequest, err => { + assert.ifError(err); + done(); + }); }); }); }); }); - }); - - it('Test executeSql', done => { - const createSessionRequest = {database: _DATABASE}; - client.createSession(createSessionRequest, (err, session) => { - assert.ifError(err); - const sessionName = session.name; - - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 1); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - const executeSqlRequest = { - session: sessionName, - sql: _TEST_SQL, - }; - client.executeSql(executeSqlRequest, (err, resultSet) => { + it('Test executeSql', done => { + const createSessionRequest = {database: _DATABASE}; + client.createSession(createSessionRequest, (err, session) => { assert.ifError(err); - assert.notStrictEqual(resultSet, null); - const rowsList = resultSet.rows; - const value = rowsList[0].values[0].stringValue; + const sessionName = session.name; - assert.strictEqual(value, 'payload'); assert.strictEqual(pool.channelRefs.length, 1); assert.strictEqual(pool.channelRefs[0].affinityCount, 1); assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - const deleteSessionRequest = {name: sessionName}; - client.deleteSession(deleteSessionRequest, err => { + const executeSqlRequest = { + session: sessionName, + sql: _TEST_SQL, + }; + client.executeSql(executeSqlRequest, (err, resultSet) => { assert.ifError(err); + assert.notStrictEqual(resultSet, null); + const rowsList = resultSet.rows; + const value = rowsList[0].values[0].stringValue; + + assert.strictEqual(value, 'payload'); assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 0); + assert.strictEqual(pool.channelRefs[0].affinityCount, 1); assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - done(); + + const deleteSessionRequest = {name: sessionName}; + client.deleteSession(deleteSessionRequest, err => { + assert.ifError(err); + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 0); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); + done(); + }); }); }); }); - }); - - it('Test executeStreamingSql', done => { - const createSessionRequest = {database: _DATABASE}; - client.createSession(createSessionRequest, (err, session) => { - assert.ifError(err); - const sessionName = session.name; - - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 1); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - const executeSqlRequest = { - session: sessionName, - sql: _TEST_SQL, - }; - const call = client.executeStreamingSql(executeSqlRequest); + it('Test executeStreamingSql', done => { + const createSessionRequest = {database: _DATABASE}; + client.createSession(createSessionRequest, (err, session) => { + assert.ifError(err); + const sessionName = session.name; - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 1); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 1); + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 1); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - call.on('data', partialResultSet => { - const value = partialResultSet.values[0].stringValue; - assert.strictEqual(value, 'payload'); - }); + const executeSqlRequest = { + session: sessionName, + sql: _TEST_SQL, + }; + const call = client.executeStreamingSql(executeSqlRequest); - call.on('status', status => { - assert.strictEqual(status.code, grpc.status.OK); assert.strictEqual(pool.channelRefs.length, 1); assert.strictEqual(pool.channelRefs[0].affinityCount, 1); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - }); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 1); - call.on('end', () => { - const deleteSessionRequest = {name: sessionName}; - client.deleteSession(deleteSessionRequest, err => { - assert.ifError(err); + call.on('data', partialResultSet => { + const value = partialResultSet.values[0].stringValue; + assert.strictEqual(value, 'payload'); + }); + + call.on('status', status => { + assert.strictEqual(status.code, grpc.status.OK); assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 0); + assert.strictEqual(pool.channelRefs[0].affinityCount, 1); assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - done(); + }); + + call.on('end', () => { + const deleteSessionRequest = {name: sessionName}; + client.deleteSession(deleteSessionRequest, err => { + assert.ifError(err); + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 0); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); + done(); + }); }); }); }); - }); - it('Test concurrent streams watermark', done => { - const watermark = 5; - pool.maxConcurrentStreamsLowWatermark = watermark; - - const expectedNumChannels = 3; - - const createCallPromises = []; - - for (let i = 0; i < watermark * expectedNumChannels; i++) { - const promise = new Promise((resolve, reject) => { - const createSessionRequest = {database: _DATABASE}; - client.createSession(createSessionRequest, (err, session) => { - if (err) { - reject(err); - } else { - const executeSqlRequest = { - session: session.name, - sql: _TEST_SQL, - }; - const call = client.executeStreamingSql(executeSqlRequest); - - resolve({ - call: call, - sessionName: session.name, - }); - } + it('Test concurrent streams watermark', done => { + const watermark = 5; + pool.maxConcurrentStreamsLowWatermark = watermark; + + const expectedNumChannels = 3; + + const createCallPromises = []; + + for (let i = 0; i < watermark * expectedNumChannels; i++) { + const promise = new Promise((resolve, reject) => { + const createSessionRequest = {database: _DATABASE}; + client.createSession(createSessionRequest, (err, session) => { + if (err) { + reject(err); + } else { + const executeSqlRequest = { + session: session.name, + sql: _TEST_SQL, + }; + const call = client.executeStreamingSql(executeSqlRequest); + + resolve({ + call: call, + sessionName: session.name, + }); + } + }); }); - }); - createCallPromises.push(promise); - } - - Promise.all(createCallPromises) - .then( - results => { - assert.strictEqual( - pool.channelRefs.length, - expectedNumChannels - ); - assert.strictEqual( - pool.channelRefs[0].affinityCount, - watermark - ); - assert.strictEqual( - pool.channelRefs[0].activeStreamsCount, - watermark - ); - - // Consume streaming calls. - const emitterPromises = results.map( - result => - new Promise(resolve => { - result.call.on('data', partialResultSet => { - const value = partialResultSet.values[0].stringValue; - assert.strictEqual(value, 'payload'); - }); - result.call.on('end', () => { - const deleteSessionRequest = {name: result.sessionName}; - client.deleteSession(deleteSessionRequest, err => { - assert.ifError(err); - resolve(); + createCallPromises.push(promise); + } + + Promise.all(createCallPromises) + .then( + results => { + assert.strictEqual( + pool.channelRefs.length, + expectedNumChannels + ); + assert.strictEqual( + pool.channelRefs[0].affinityCount, + watermark + ); + assert.strictEqual( + pool.channelRefs[0].activeStreamsCount, + watermark + ); + + // Consume streaming calls. + const emitterPromises = results.map( + result => + new Promise(resolve => { + result.call.on('data', partialResultSet => { + const value = partialResultSet.values[0].stringValue; + assert.strictEqual(value, 'payload'); }); - }); - }) - ); - - // Make sure all sessions get cleaned. - return Promise.all(emitterPromises); - }, - error => { - done(error); - } - ) - .then( - () => { - assert.strictEqual( - pool.channelRefs.length, - expectedNumChannels - ); - assert.strictEqual(pool.channelRefs[0].affinityCount, 0); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - done(); - }, - error => { - done(error); - } - ); - }); + result.call.on('end', () => { + const deleteSessionRequest = {name: result.sessionName}; + client.deleteSession(deleteSessionRequest, err => { + assert.ifError(err); + resolve(); + }); + }); + }) + ); + + // Make sure all sessions get cleaned. + return Promise.all(emitterPromises); + }, + error => { + done(error); + } + ) + .then( + () => { + assert.strictEqual( + pool.channelRefs.length, + expectedNumChannels + ); + assert.strictEqual(pool.channelRefs[0].affinityCount, 0); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); + done(); + }, + error => { + done(error); + } + ); + }); - it('Test invalid BOUND affinity', done => { - const getSessionRequest = {name: 'wrong_name'}; - client.getSession(getSessionRequest, err => { - assert(err); - assert.strictEqual( - err.message, - '3 INVALID_ARGUMENT: Invalid GetSession request.' - ); - done(); + it('Test invalid BOUND affinity', done => { + const getSessionRequest = {name: 'wrong_name'}; + client.getSession(getSessionRequest, err => { + assert(err); + assert.strictEqual( + err.message, + '3 INVALID_ARGUMENT: Invalid GetSession request.' + ); + done(); + }); }); - }); - it('Test invalid UNBIND affinity', done => { - const deleteSessionRequest = {name: 'wrong_name'}; - client.deleteSession(deleteSessionRequest, err => { - assert(err); - assert.strictEqual( - err.message, - '3 INVALID_ARGUMENT: Invalid DeleteSession request.' - ); - done(); + it('Test invalid UNBIND affinity', done => { + const deleteSessionRequest = {name: 'wrong_name'}; + client.deleteSession(deleteSessionRequest, err => { + assert(err); + assert.strictEqual( + err.message, + '3 INVALID_ARGUMENT: Invalid DeleteSession request.' + ); + done(); + }); }); }); - }); - describe('SpannerClient generated by google-gax', () => { - const gaxGrpc = new gax.GrpcClient({grpc}); - const protos = gaxGrpc.loadProto( - PROTO_DIR, - 'google/spanner/v1/spanner.proto' - ); - const SpannerClient = protos.google.spanner.v1.Spanner; - - let client; - let pool; + describe('SpannerClient generated by google-gax', () => { + const gaxGrpc = new gax.GrpcClient({grpc}); + const protos = gaxGrpc.loadProto( + PROTO_DIR, + 'google/spanner/v1/spanner.proto' + ); + const SpannerClient = protos.google.spanner.v1.Spanner; - beforeEach(async () => { - const authFactory = new GoogleAuth({ - scopes: [_OAUTH_SCOPE], - }); - const auth = await authFactory.getClient(); + let client; + let pool; - const sslCreds = grpc.credentials.createSsl(); - const callCreds = grpc.credentials.createFromGoogleCredential(auth); - const channelCreds = grpc.credentials.combineChannelCredentials( - sslCreds, - callCreds - ); + beforeEach(async () => { + const authFactory = new GoogleAuth({ + scopes: [_OAUTH_SCOPE], + }); + const auth = await authFactory.getClient(); - const apiDefinition = JSON.parse(fs.readFileSync(_CONFIG_FILE)); - const apiConfig = grpcGcp.createGcpApiConfig(apiDefinition); + const sslCreds = grpc.credentials.createSsl(); + const callCreds = grpc.credentials.createFromGoogleCredential(auth); + const channelCreds = grpc.credentials.combineChannelCredentials( + sslCreds, + callCreds + ); - const channelOptions = { - channelFactoryOverride: grpcGcp.gcpChannelFactoryOverride, - callInvocationTransformer: grpcGcp.gcpCallInvocationTransformer, - gcpApiConfig: apiConfig, - }; + const apiDefinition = JSON.parse(fs.readFileSync(_CONFIG_FILE)); + const apiConfig = grpcGcp.createGcpApiConfig(apiDefinition); - client = new SpannerClient(_TARGET, channelCreds, channelOptions); - pool = client.getChannel(); - }); + const channelOptions = { + channelFactoryOverride: grpcGcp.gcpChannelFactoryOverride, + callInvocationTransformer: grpcGcp.gcpCallInvocationTransformer, + gcpApiConfig: apiConfig, + }; - it('Test session operations', done => { - client.createSession({database: _DATABASE}, (err, session) => { - assert.ifError(err); - const sessionName = session.name; + client = new SpannerClient(_TARGET, channelCreds, channelOptions); + pool = client.getChannel(); + }); - client.getSession({name: sessionName}, (err, sessionResult) => { + it('Test session operations', done => { + client.createSession({database: _DATABASE}, (err, session) => { assert.ifError(err); - assert.strictEqual(sessionResult.name, sessionName); + const sessionName = session.name; - client.listSessions({database: _DATABASE}, (err, response) => { + client.getSession({name: sessionName}, (err, sessionResult) => { assert.ifError(err); - const sessionsList = response.sessions; - const sessionNames = sessionsList.map(session => session.name); - assert(sessionNames.includes(sessionName)); + assert.strictEqual(sessionResult.name, sessionName); - client.deleteSession({name: sessionName}, err => { + client.listSessions({database: _DATABASE}, (err, response) => { assert.ifError(err); - done(); + const sessionsList = response.sessions; + const sessionNames = sessionsList.map(session => session.name); + assert(sessionNames.includes(sessionName)); + + client.deleteSession({name: sessionName}, err => { + assert.ifError(err); + done(); + }); }); }); }); }); - }); - - it('Test executeSql', done => { - client.createSession({database: _DATABASE}, (err, session) => { - assert.ifError(err); - const sessionName = session.name; - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 1); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - - const executeSqlRequest = { - session: sessionName, - sql: _TEST_SQL, - }; - client.executeSql(executeSqlRequest, (err, resultSet) => { + it('Test executeSql', done => { + client.createSession({database: _DATABASE}, (err, session) => { assert.ifError(err); - assert.notStrictEqual(resultSet, null); - const rowsList = resultSet.rows; - const value = rowsList[0].values[0].stringValue; + const sessionName = session.name; - assert.strictEqual(value, 'payload'); assert.strictEqual(pool.channelRefs.length, 1); assert.strictEqual(pool.channelRefs[0].affinityCount, 1); assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - const deleteSessionRequest = {name: sessionName}; - client.deleteSession(deleteSessionRequest, err => { + const executeSqlRequest = { + session: sessionName, + sql: _TEST_SQL, + }; + client.executeSql(executeSqlRequest, (err, resultSet) => { assert.ifError(err); + assert.notStrictEqual(resultSet, null); + const rowsList = resultSet.rows; + const value = rowsList[0].values[0].stringValue; + + assert.strictEqual(value, 'payload'); assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 0); + assert.strictEqual(pool.channelRefs[0].affinityCount, 1); assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - done(); + + const deleteSessionRequest = {name: sessionName}; + client.deleteSession(deleteSessionRequest, err => { + assert.ifError(err); + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 0); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); + done(); + }); }); }); }); - }); - - it('Test executeStreamingSql', done => { - client.createSession({database: _DATABASE}, (err, session) => { - assert.ifError(err); - const sessionName = session.name; - - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 1); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - const executeSqlRequest = { - session: sessionName, - sql: _TEST_SQL, - }; - const call = client.executeStreamingSql(executeSqlRequest); + it('Test executeStreamingSql', done => { + client.createSession({database: _DATABASE}, (err, session) => { + assert.ifError(err); + const sessionName = session.name; - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 1); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 1); + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 1); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - call.on('data', partialResultSet => { - const value = partialResultSet.values[0].stringValue; - assert.strictEqual(value, 'payload'); - }); + const executeSqlRequest = { + session: sessionName, + sql: _TEST_SQL, + }; + const call = client.executeStreamingSql(executeSqlRequest); - call.on('status', status => { - assert.strictEqual(status.code, grpc.status.OK); assert.strictEqual(pool.channelRefs.length, 1); assert.strictEqual(pool.channelRefs[0].affinityCount, 1); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - }); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 1); - call.on('end', () => { - client.deleteSession({name: sessionName}, err => { - assert.ifError(err); + call.on('data', partialResultSet => { + const value = partialResultSet.values[0].stringValue; + assert.strictEqual(value, 'payload'); + }); + + call.on('status', status => { + assert.strictEqual(status.code, grpc.status.OK); assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 0); + assert.strictEqual(pool.channelRefs[0].affinityCount, 1); assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - done(); + }); + + call.on('end', () => { + client.deleteSession({name: sessionName}, err => { + assert.ifError(err); + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 0); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); + done(); + }); }); }); }); }); }); }); - }); -} + } +}); From 2a0c5f581cd719725ff149631bd0612dcace39b4 Mon Sep 17 00:00:00 2001 From: Yuri Golobokov Date: Fri, 16 Jul 2021 15:55:52 -0700 Subject: [PATCH 12/12] Split Spanner integration tests. Split Spanner integration tests into different processes to avoid interceptors confusion. --- package.json | 2 +- test/integration/spanner_test.js | 701 +++++++++++++++---------------- 2 files changed, 351 insertions(+), 352 deletions(-) diff --git a/package.json b/package.json index 8f9bb93..14d8eff 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "build/src/index.js", "scripts": { "build": "tsc && cp -r src/generated build/src/", - "system-test": "c8 mocha test/integration/*.js --reporter spec --timeout 10000", + "system-test": "c8 mocha test/integration/*.js --reporter spec --timeout 10000 --grpclib grpc && c8 mocha test/integration/*.js --reporter spec --timeout 10000 --grpclib @grpc/grpc-js", "test": "c8 mocha test/unit/*.js --reporter spec", "lint": "gts check src/**/*.ts", "fix": "gts fix", diff --git a/test/integration/spanner_test.js b/test/integration/spanner_test.js index 94d35af..ea9443d 100644 --- a/test/integration/spanner_test.js +++ b/test/integration/spanner_test.js @@ -49,9 +49,12 @@ const getGrpcGcpObjects = require('../../build/src'); const spanner = new Spanner({projectId: _PROJECT_ID}); const instance = spanner.instance(_INSTANCE_ID); -describe("Spanner integration tests", () => { +const argIndex = process.argv.findIndex(value => value === '--grpclib'); +assert.notStrictEqual(argIndex, -1, 'Please, specify grpc lib with --grpclib'); +const grpcLibName = process.argv[argIndex + 1]; - before(async function() { +describe('Using ' + grpcLibName, () => { + before(async function () { this.timeout(60000); // Create test instance. console.log(`Creating instance ${instance.formattedName_}.`); @@ -97,7 +100,7 @@ describe("Spanner integration tests", () => { console.log(`Row inserted into table "${_TABLE_NAME}".`); }); - after(async function() { + after(async function () { this.timeout(60000); // Delete test instance. console.log(`Deleting instance ${instance.id}...`); @@ -105,414 +108,410 @@ describe("Spanner integration tests", () => { console.log(`Deleted instance ${_INSTANCE_ID}.`); }); - for (const grpcLibName of ['grpc', '@grpc/grpc-js']) { - describe('Using ' + grpcLibName, () => { - const grpc = require(grpcLibName); - const grpcGcp = getGrpcGcpObjects(grpc); - describe('Spanner integration tests', () => { - describe('SpannerClient generated by jspb', () => { - const spannerPackageDef = protoLoader.loadSync( - PROTO_DIR + '/google/spanner/v1/spanner.proto', - {includeDirs: [PROTO_DIR]} - ); - const spannerGrpc = grpc.loadPackageDefinition(spannerPackageDef); - - let client; - let pool; - - beforeEach(async () => { - const authFactory = new GoogleAuth(); - const auth = await authFactory.getClient(); - - const sslCreds = grpc.credentials.createSsl(); - const callCreds = grpc.credentials.createFromGoogleCredential(auth); - const channelCreds = grpc.credentials.combineChannelCredentials( - sslCreds, - callCreds - ); - - const apiDefinition = JSON.parse(fs.readFileSync(_CONFIG_FILE)); - const apiConfig = grpcGcp.createGcpApiConfig(apiDefinition); - - const channelOptions = { - channelFactoryOverride: grpcGcp.gcpChannelFactoryOverride, - callInvocationTransformer: grpcGcp.gcpCallInvocationTransformer, - gcpApiConfig: apiConfig, - }; - - client = new spannerGrpc.google.spanner.v1.Spanner( - _TARGET, - channelCreds, - channelOptions - ); - - pool = client.getChannel(); - }); + const grpc = require(grpcLibName); + const grpcGcp = getGrpcGcpObjects(grpc); + describe('Spanner integration tests', () => { + describe('SpannerClient generated by jspb', () => { + const spannerPackageDef = protoLoader.loadSync( + PROTO_DIR + '/google/spanner/v1/spanner.proto', + {includeDirs: [PROTO_DIR]} + ); + const spannerGrpc = grpc.loadPackageDefinition(spannerPackageDef); + + let client; + let pool; + + beforeEach(async () => { + const authFactory = new GoogleAuth(); + const auth = await authFactory.getClient(); + + const sslCreds = grpc.credentials.createSsl(); + const callCreds = grpc.credentials.createFromGoogleCredential(auth); + const channelCreds = grpc.credentials.combineChannelCredentials( + sslCreds, + callCreds + ); + + const apiDefinition = JSON.parse(fs.readFileSync(_CONFIG_FILE)); + const apiConfig = grpcGcp.createGcpApiConfig(apiDefinition); + + const channelOptions = { + channelFactoryOverride: grpcGcp.gcpChannelFactoryOverride, + callInvocationTransformer: grpcGcp.gcpCallInvocationTransformer, + gcpApiConfig: apiConfig, + }; + + client = new spannerGrpc.google.spanner.v1.Spanner( + _TARGET, + channelCreds, + channelOptions + ); + + pool = client.getChannel(); + }); - it('Test session operations', done => { - const createSessionRequest = {database: _DATABASE}; - client.createSession(createSessionRequest, (err, session) => { + it('Test session operations', done => { + const createSessionRequest = {database: _DATABASE}; + client.createSession(createSessionRequest, (err, session) => { + assert.ifError(err); + const sessionName = session.name; + + const getSessionRequest = {name: sessionName}; + client.getSession(getSessionRequest, (err, sessionResult) => { + assert.ifError(err); + assert.strictEqual(sessionResult.name, sessionName); + + const listSessionsRequest = {database: _DATABASE}; + client.listSessions(listSessionsRequest, (err, response) => { assert.ifError(err); - const sessionName = session.name; + const sessionsList = response.sessions; + const sessionNames = sessionsList.map(session => session.name); + assert(sessionNames.includes(sessionName)); - const getSessionRequest = {name: sessionName}; - client.getSession(getSessionRequest, (err, sessionResult) => { + const deleteSessionRequest = {name: sessionName}; + client.deleteSession(deleteSessionRequest, err => { assert.ifError(err); - assert.strictEqual(sessionResult.name, sessionName); - - const listSessionsRequest = {database: _DATABASE}; - client.listSessions(listSessionsRequest, (err, response) => { - assert.ifError(err); - const sessionsList = response.sessions; - const sessionNames = sessionsList.map(session => session.name); - assert(sessionNames.includes(sessionName)); - - const deleteSessionRequest = {name: sessionName}; - client.deleteSession(deleteSessionRequest, err => { - assert.ifError(err); - done(); - }); - }); + done(); }); }); }); + }); + }); - it('Test executeSql', done => { - const createSessionRequest = {database: _DATABASE}; - client.createSession(createSessionRequest, (err, session) => { + it('Test executeSql', done => { + const createSessionRequest = {database: _DATABASE}; + client.createSession(createSessionRequest, (err, session) => { + assert.ifError(err); + const sessionName = session.name; + + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 1); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); + + const executeSqlRequest = { + session: sessionName, + sql: _TEST_SQL, + }; + client.executeSql(executeSqlRequest, (err, resultSet) => { + assert.ifError(err); + assert.notStrictEqual(resultSet, null); + const rowsList = resultSet.rows; + const value = rowsList[0].values[0].stringValue; + + assert.strictEqual(value, 'payload'); + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 1); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); + + const deleteSessionRequest = {name: sessionName}; + client.deleteSession(deleteSessionRequest, err => { assert.ifError(err); - const sessionName = session.name; - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 0); assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - - const executeSqlRequest = { - session: sessionName, - sql: _TEST_SQL, - }; - client.executeSql(executeSqlRequest, (err, resultSet) => { - assert.ifError(err); - assert.notStrictEqual(resultSet, null); - const rowsList = resultSet.rows; - const value = rowsList[0].values[0].stringValue; - - assert.strictEqual(value, 'payload'); - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 1); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - - const deleteSessionRequest = {name: sessionName}; - client.deleteSession(deleteSessionRequest, err => { - assert.ifError(err); - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 0); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - done(); - }); - }); + done(); }); }); + }); + }); - it('Test executeStreamingSql', done => { - const createSessionRequest = {database: _DATABASE}; - client.createSession(createSessionRequest, (err, session) => { - assert.ifError(err); - const sessionName = session.name; + it('Test executeStreamingSql', done => { + const createSessionRequest = {database: _DATABASE}; + client.createSession(createSessionRequest, (err, session) => { + assert.ifError(err); + const sessionName = session.name; + + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 1); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); + + const executeSqlRequest = { + session: sessionName, + sql: _TEST_SQL, + }; + const call = client.executeStreamingSql(executeSqlRequest); + + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 1); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 1); + + call.on('data', partialResultSet => { + const value = partialResultSet.values[0].stringValue; + assert.strictEqual(value, 'payload'); + }); + + call.on('status', status => { + assert.strictEqual(status.code, grpc.status.OK); + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 1); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); + }); + call.on('end', () => { + const deleteSessionRequest = {name: sessionName}; + client.deleteSession(deleteSessionRequest, err => { + assert.ifError(err); assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 0); assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); + done(); + }); + }); + }); + }); - const executeSqlRequest = { - session: sessionName, - sql: _TEST_SQL, - }; - const call = client.executeStreamingSql(executeSqlRequest); - - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 1); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 1); + it('Test concurrent streams watermark', done => { + const watermark = 5; + pool.maxConcurrentStreamsLowWatermark = watermark; - call.on('data', partialResultSet => { - const value = partialResultSet.values[0].stringValue; - assert.strictEqual(value, 'payload'); - }); + const expectedNumChannels = 3; - call.on('status', status => { - assert.strictEqual(status.code, grpc.status.OK); - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 1); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - }); + const createCallPromises = []; - call.on('end', () => { - const deleteSessionRequest = {name: sessionName}; - client.deleteSession(deleteSessionRequest, err => { - assert.ifError(err); - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 0); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - done(); + for (let i = 0; i < watermark * expectedNumChannels; i++) { + const promise = new Promise((resolve, reject) => { + const createSessionRequest = {database: _DATABASE}; + client.createSession(createSessionRequest, (err, session) => { + if (err) { + reject(err); + } else { + const executeSqlRequest = { + session: session.name, + sql: _TEST_SQL, + }; + const call = client.executeStreamingSql(executeSqlRequest); + + resolve({ + call: call, + sessionName: session.name, }); - }); + } }); }); + createCallPromises.push(promise); + } - it('Test concurrent streams watermark', done => { - const watermark = 5; - pool.maxConcurrentStreamsLowWatermark = watermark; - - const expectedNumChannels = 3; - - const createCallPromises = []; - - for (let i = 0; i < watermark * expectedNumChannels; i++) { - const promise = new Promise((resolve, reject) => { - const createSessionRequest = {database: _DATABASE}; - client.createSession(createSessionRequest, (err, session) => { - if (err) { - reject(err); - } else { - const executeSqlRequest = { - session: session.name, - sql: _TEST_SQL, - }; - const call = client.executeStreamingSql(executeSqlRequest); - - resolve({ - call: call, - sessionName: session.name, - }); - } - }); - }); - createCallPromises.push(promise); - } - - Promise.all(createCallPromises) - .then( - results => { - assert.strictEqual( - pool.channelRefs.length, - expectedNumChannels - ); - assert.strictEqual( - pool.channelRefs[0].affinityCount, - watermark - ); - assert.strictEqual( - pool.channelRefs[0].activeStreamsCount, - watermark - ); - - // Consume streaming calls. - const emitterPromises = results.map( - result => - new Promise(resolve => { - result.call.on('data', partialResultSet => { - const value = partialResultSet.values[0].stringValue; - assert.strictEqual(value, 'payload'); - }); - result.call.on('end', () => { - const deleteSessionRequest = {name: result.sessionName}; - client.deleteSession(deleteSessionRequest, err => { - assert.ifError(err); - resolve(); - }); - }); - }) - ); - - // Make sure all sessions get cleaned. - return Promise.all(emitterPromises); - }, - error => { - done(error); - } - ) - .then( - () => { - assert.strictEqual( - pool.channelRefs.length, - expectedNumChannels - ); - assert.strictEqual(pool.channelRefs[0].affinityCount, 0); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - done(); - }, - error => { - done(error); - } + Promise.all(createCallPromises) + .then( + results => { + assert.strictEqual( + pool.channelRefs.length, + expectedNumChannels ); - }); - - it('Test invalid BOUND affinity', done => { - const getSessionRequest = {name: 'wrong_name'}; - client.getSession(getSessionRequest, err => { - assert(err); assert.strictEqual( - err.message, - '3 INVALID_ARGUMENT: Invalid GetSession request.' + pool.channelRefs[0].affinityCount, + watermark + ); + assert.strictEqual( + pool.channelRefs[0].activeStreamsCount, + watermark ); - done(); - }); - }); - it('Test invalid UNBIND affinity', done => { - const deleteSessionRequest = {name: 'wrong_name'}; - client.deleteSession(deleteSessionRequest, err => { - assert(err); + // Consume streaming calls. + const emitterPromises = results.map( + result => + new Promise(resolve => { + result.call.on('data', partialResultSet => { + const value = partialResultSet.values[0].stringValue; + assert.strictEqual(value, 'payload'); + }); + result.call.on('end', () => { + const deleteSessionRequest = {name: result.sessionName}; + client.deleteSession(deleteSessionRequest, err => { + assert.ifError(err); + resolve(); + }); + }); + }) + ); + + // Make sure all sessions get cleaned. + return Promise.all(emitterPromises); + }, + error => { + done(error); + } + ) + .then( + () => { assert.strictEqual( - err.message, - '3 INVALID_ARGUMENT: Invalid DeleteSession request.' + pool.channelRefs.length, + expectedNumChannels ); + assert.strictEqual(pool.channelRefs[0].affinityCount, 0); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); done(); - }); - }); + }, + error => { + done(error); + } + ); + }); + + it('Test invalid BOUND affinity', done => { + const getSessionRequest = {name: 'wrong_name'}; + client.getSession(getSessionRequest, err => { + assert(err); + assert.strictEqual( + err.message, + '3 INVALID_ARGUMENT: Invalid GetSession request.' + ); + done(); }); + }); - describe('SpannerClient generated by google-gax', () => { - const gaxGrpc = new gax.GrpcClient({grpc}); - const protos = gaxGrpc.loadProto( - PROTO_DIR, - 'google/spanner/v1/spanner.proto' + it('Test invalid UNBIND affinity', done => { + const deleteSessionRequest = {name: 'wrong_name'}; + client.deleteSession(deleteSessionRequest, err => { + assert(err); + assert.strictEqual( + err.message, + '3 INVALID_ARGUMENT: Invalid DeleteSession request.' ); - const SpannerClient = protos.google.spanner.v1.Spanner; + done(); + }); + }); + }); - let client; - let pool; + describe('SpannerClient generated by google-gax', () => { + const gaxGrpc = new gax.GrpcClient({grpc}); + const protos = gaxGrpc.loadProto( + PROTO_DIR, + 'google/spanner/v1/spanner.proto' + ); + const SpannerClient = protos.google.spanner.v1.Spanner; - beforeEach(async () => { - const authFactory = new GoogleAuth({ - scopes: [_OAUTH_SCOPE], - }); - const auth = await authFactory.getClient(); - - const sslCreds = grpc.credentials.createSsl(); - const callCreds = grpc.credentials.createFromGoogleCredential(auth); - const channelCreds = grpc.credentials.combineChannelCredentials( - sslCreds, - callCreds - ); - - const apiDefinition = JSON.parse(fs.readFileSync(_CONFIG_FILE)); - const apiConfig = grpcGcp.createGcpApiConfig(apiDefinition); - - const channelOptions = { - channelFactoryOverride: grpcGcp.gcpChannelFactoryOverride, - callInvocationTransformer: grpcGcp.gcpCallInvocationTransformer, - gcpApiConfig: apiConfig, - }; - - client = new SpannerClient(_TARGET, channelCreds, channelOptions); - pool = client.getChannel(); - }); + let client; + let pool; - it('Test session operations', done => { - client.createSession({database: _DATABASE}, (err, session) => { + beforeEach(async () => { + const authFactory = new GoogleAuth({ + scopes: [_OAUTH_SCOPE], + }); + const auth = await authFactory.getClient(); + + const sslCreds = grpc.credentials.createSsl(); + const callCreds = grpc.credentials.createFromGoogleCredential(auth); + const channelCreds = grpc.credentials.combineChannelCredentials( + sslCreds, + callCreds + ); + + const apiDefinition = JSON.parse(fs.readFileSync(_CONFIG_FILE)); + const apiConfig = grpcGcp.createGcpApiConfig(apiDefinition); + + const channelOptions = { + channelFactoryOverride: grpcGcp.gcpChannelFactoryOverride, + callInvocationTransformer: grpcGcp.gcpCallInvocationTransformer, + gcpApiConfig: apiConfig, + }; + + client = new SpannerClient(_TARGET, channelCreds, channelOptions); + pool = client.getChannel(); + }); + + it('Test session operations', done => { + client.createSession({database: _DATABASE}, (err, session) => { + assert.ifError(err); + const sessionName = session.name; + + client.getSession({name: sessionName}, (err, sessionResult) => { + assert.ifError(err); + assert.strictEqual(sessionResult.name, sessionName); + + client.listSessions({database: _DATABASE}, (err, response) => { assert.ifError(err); - const sessionName = session.name; + const sessionsList = response.sessions; + const sessionNames = sessionsList.map(session => session.name); + assert(sessionNames.includes(sessionName)); - client.getSession({name: sessionName}, (err, sessionResult) => { + client.deleteSession({name: sessionName}, err => { assert.ifError(err); - assert.strictEqual(sessionResult.name, sessionName); - - client.listSessions({database: _DATABASE}, (err, response) => { - assert.ifError(err); - const sessionsList = response.sessions; - const sessionNames = sessionsList.map(session => session.name); - assert(sessionNames.includes(sessionName)); - - client.deleteSession({name: sessionName}, err => { - assert.ifError(err); - done(); - }); - }); + done(); }); }); }); + }); + }); - it('Test executeSql', done => { - client.createSession({database: _DATABASE}, (err, session) => { + it('Test executeSql', done => { + client.createSession({database: _DATABASE}, (err, session) => { + assert.ifError(err); + const sessionName = session.name; + + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 1); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); + + const executeSqlRequest = { + session: sessionName, + sql: _TEST_SQL, + }; + client.executeSql(executeSqlRequest, (err, resultSet) => { + assert.ifError(err); + assert.notStrictEqual(resultSet, null); + const rowsList = resultSet.rows; + const value = rowsList[0].values[0].stringValue; + + assert.strictEqual(value, 'payload'); + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 1); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); + + const deleteSessionRequest = {name: sessionName}; + client.deleteSession(deleteSessionRequest, err => { assert.ifError(err); - const sessionName = session.name; - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 0); assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - - const executeSqlRequest = { - session: sessionName, - sql: _TEST_SQL, - }; - client.executeSql(executeSqlRequest, (err, resultSet) => { - assert.ifError(err); - assert.notStrictEqual(resultSet, null); - const rowsList = resultSet.rows; - const value = rowsList[0].values[0].stringValue; - - assert.strictEqual(value, 'payload'); - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 1); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - - const deleteSessionRequest = {name: sessionName}; - client.deleteSession(deleteSessionRequest, err => { - assert.ifError(err); - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 0); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - done(); - }); - }); + done(); }); }); + }); + }); - it('Test executeStreamingSql', done => { - client.createSession({database: _DATABASE}, (err, session) => { - assert.ifError(err); - const sessionName = session.name; + it('Test executeStreamingSql', done => { + client.createSession({database: _DATABASE}, (err, session) => { + assert.ifError(err); + const sessionName = session.name; - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 1); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 1); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - const executeSqlRequest = { - session: sessionName, - sql: _TEST_SQL, - }; - const call = client.executeStreamingSql(executeSqlRequest); + const executeSqlRequest = { + session: sessionName, + sql: _TEST_SQL, + }; + const call = client.executeStreamingSql(executeSqlRequest); - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 1); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 1); + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 1); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 1); - call.on('data', partialResultSet => { - const value = partialResultSet.values[0].stringValue; - assert.strictEqual(value, 'payload'); - }); + call.on('data', partialResultSet => { + const value = partialResultSet.values[0].stringValue; + assert.strictEqual(value, 'payload'); + }); - call.on('status', status => { - assert.strictEqual(status.code, grpc.status.OK); - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 1); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - }); + call.on('status', status => { + assert.strictEqual(status.code, grpc.status.OK); + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 1); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); + }); - call.on('end', () => { - client.deleteSession({name: sessionName}, err => { - assert.ifError(err); - assert.strictEqual(pool.channelRefs.length, 1); - assert.strictEqual(pool.channelRefs[0].affinityCount, 0); - assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); - done(); - }); - }); + call.on('end', () => { + client.deleteSession({name: sessionName}, err => { + assert.ifError(err); + assert.strictEqual(pool.channelRefs.length, 1); + assert.strictEqual(pool.channelRefs[0].affinityCount, 0); + assert.strictEqual(pool.channelRefs[0].activeStreamsCount, 0); + done(); }); }); }); }); }); - } + }); });