Skip to content

Commit

Permalink
test: Mock server for testing (#1213)
Browse files Browse the repository at this point in the history
* This test makes a call to the mock server

This will be useful for debugging grpc issues.

* Now the test works with the mock server in repo

This mock server will be super useful for ensuring that the right data gets transmitted in private preview so that we can confirm the client library is working correctly.

* Delete js file

We use the ts file instead.

* Add a README and guiding steps inline

* Simplify the instructions

* minor corrections

* Resolve linting issues

* Add headers for new code

* Skip a mock server test
  • Loading branch information
danieljbruce authored Nov 18, 2024
1 parent 09b76ca commit ea17528
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 0 deletions.
15 changes: 15 additions & 0 deletions mock-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
The mock server code in this folder is used for observing requests that will
be sent to the server. When the server sends back a vague error it is often
because the request it receives is incorrect so it is crucial to have a tool to
view the request in order to know what client library code needs to change.

The steps to follow for using the mock server is:
1. Take a look at `test/try-server.ts` to see how the mock server is used.
2. In the system test you want to debug, change `it` to `it.only` to isolate that test.
3. In this test, surround the code with `startServer(async () => {`
4. Ensure `apiEndpoint: 'localhost:50051'` is passed into the datastore client that is used for this test.
5. If the system test hits an endpoint other than `runQuery` then in `datastore-server.ts`, change `.addService(service, {runQuery: grpcEndpoint})` to `.addService(service, {<<OtherGrpcEndpoint>>: grpcEndpoint})`
6. Set a breakpoint on the line that says `SET A BREAKPOINT HERE` in `datastore-server.ts`
7. Debug with system tests (Enter `npm run system-test -- --inspect` in terminal)


67 changes: 67 additions & 0 deletions mock-server/datastore-server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

const {dirname, resolve} = require('node:path');

const PROTO_PATH = __dirname + '/../protos/google/datastore/v1/datastore.proto';
const DATASTORE_PROTOS = __dirname + '/../protos';
const GAX_PROTOS_DIR = resolve(
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line n/no-extraneous-require
dirname(require.resolve('google-gax')),
'../protos'
);

const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');

const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
includeDirs: [DATASTORE_PROTOS, GAX_PROTOS_DIR],
});
const descriptor = grpc.loadPackageDefinition(packageDefinition);

/**
* Implements the runQuery RPC method.
*/
function grpcEndpoint(
call: {},
callback: (arg1: string | null, arg2: {}) => {}
) {
// SET A BREAKPOINT HERE AND EXPLORE `call` TO SEE THE REQUEST.
callback(null, {message: 'Hello'});
}

/**
* Starts an RPC server that receives requests for datastore
*/
export function startServer(cb: () => void) {
const server = new grpc.Server();
const service = descriptor.google.datastore.v1.Datastore.service;
// On the next line, change runQuery to the grpc method you want to investigate
server.addService(service, {runQuery: grpcEndpoint});
server.bindAsync(
'0.0.0.0:50051',
grpc.ServerCredentials.createInsecure(),
() => {
console.log('server started');
cb();
}
);
}
12 changes: 12 additions & 0 deletions mock-server/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "grpc-examples",
"version": "0.1.0",
"dependencies": {
"@grpc/proto-loader": "^0.5.0",
"async": "^1.5.2",
"google-protobuf": "^3.0.0",
"@grpc/grpc-js": "^1.1.0",
"lodash": "^4.6.1",
"minimist": "^1.2.0"
}
}
33 changes: 33 additions & 0 deletions test/try-server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import {describe, it} from 'mocha';
import {Datastore} from '../src';

import {startServer} from '../mock-server/datastore-server';

describe('Try server', () => {
it.skip('should try to connect to the running server', done => {
startServer(async () => {
const datastore = new Datastore({
namespace: `${Date.now()}`,
apiEndpoint: 'localhost:50051',
});
const postKey = datastore.key(['Post', 'post1']);
const query = datastore.createQuery('Post').hasAncestor(postKey);
const allResults = await datastore.runQuery(query);
done();
});
});
});

0 comments on commit ea17528

Please sign in to comment.