-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Getting grpc set up for tests * test for error sent through gax * Trying other things * Group everything into describe blocks. * Add Google header * Added more tests * Create mock service files * refactor a check * mock server tests * undo tests * Pass metadata through * build fix * work in progress * Add service error check and change test * Remove TODO and add done hook. * Logs for debugging * use the tcp-port-used library instead * use await Co-authored-by: Benjamin E. Coe <bencoe@google.com>
- Loading branch information
1 parent
b997a6b
commit ecae5f3
Showing
6 changed files
with
338 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Copyright 2022 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. | ||
// | ||
// ** This file is automatically generated by gapic-generator-typescript. ** | ||
// ** https://github.com/googleapis/gapic-generator-typescript ** | ||
// ** All changes to this file may be overwritten. ** | ||
|
||
import {grpc} from 'google-gax'; | ||
|
||
const DEFAULT_PORT = 1234; | ||
|
||
export class MockServer { | ||
port: string; | ||
services: Set<grpc.ServiceDefinition> = new Set(); | ||
server: grpc.Server; | ||
|
||
constructor( | ||
callback?: (port: string) => void, | ||
port?: string | number | undefined | ||
) { | ||
const portString = Number(port ? port : DEFAULT_PORT).toString(); | ||
this.port = portString; | ||
const server = new grpc.Server(); | ||
this.server = server; | ||
server.bindAsync( | ||
`localhost:${this.port}`, | ||
grpc.ServerCredentials.createInsecure(), | ||
() => { | ||
server.start(); | ||
callback ? callback(portString) : undefined; | ||
} | ||
); | ||
} | ||
|
||
setService( | ||
service: grpc.ServiceDefinition, | ||
implementation: grpc.UntypedServiceImplementation | ||
) { | ||
if (this.services.has(service)) { | ||
this.server.removeService(service); | ||
} else { | ||
this.services.add(service); | ||
} | ||
this.server.addService(service, implementation); | ||
} | ||
|
||
shutdown(callback: (err?: Error) => void) { | ||
this.server.tryShutdown((err?: Error) => { | ||
callback(err); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// Copyright 2022 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. | ||
// | ||
// ** This file is automatically generated by gapic-generator-typescript. ** | ||
// ** https://github.com/googleapis/gapic-generator-typescript ** | ||
// ** All changes to this file may be overwritten. ** | ||
|
||
import {grpc} from 'google-gax'; | ||
|
||
import {MockServer} from './mock-server'; | ||
|
||
export abstract class MockService { | ||
abstract service: grpc.ServiceDefinition; | ||
server: MockServer; | ||
|
||
constructor(server: MockServer) { | ||
this.server = server; | ||
} | ||
|
||
setService(implementation: grpc.UntypedServiceImplementation) { | ||
this.server.setService(this.service, implementation); | ||
} | ||
} |
38 changes: 38 additions & 0 deletions
38
src/util/mock-servers/service-implementations/bigtable-client-mock-service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
// Copyright 2022 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. | ||
// | ||
// ** This file is automatically generated by gapic-generator-typescript. ** | ||
// ** https://github.com/googleapis/gapic-generator-typescript ** | ||
// ** All changes to this file may be overwritten. ** | ||
|
||
import grpc = require('@grpc/grpc-js'); | ||
import jsonProtos = require('../../../../protos/protos.json'); | ||
import protoLoader = require('@grpc/proto-loader'); | ||
import {MockService} from '../mock-service'; | ||
|
||
const packageDefinition = protoLoader.fromJSON(jsonProtos, { | ||
keepCase: true, | ||
longs: String, | ||
enums: String, | ||
defaults: true, | ||
oneofs: true, | ||
}); | ||
const proto = grpc.loadPackageDefinition(packageDefinition); | ||
|
||
export class BigtableClientMockService extends MockService { | ||
service = | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore | ||
proto.google.bigtable.v2.Bigtable.service; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
// Copyright 2022 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. | ||
// | ||
// ** This file is automatically generated by gapic-generator-typescript. ** | ||
// ** https://github.com/googleapis/gapic-generator-typescript ** | ||
// ** All changes to this file may be overwritten. ** | ||
|
||
import {before, describe, it} from 'mocha'; | ||
import {Bigtable} from '../src'; | ||
import * as assert from 'assert'; | ||
|
||
import {GoogleError, grpc, ServiceError} from 'google-gax'; | ||
import {MockServer} from '../src/util/mock-servers/mock-server'; | ||
import {BigtableClientMockService} from '../src/util/mock-servers/service-implementations/bigtable-client-mock-service'; | ||
import {MockService} from '../src/util/mock-servers/mock-service'; | ||
|
||
function isServiceError(error: any): error is ServiceError { | ||
return ( | ||
error.code !== undefined && | ||
error.details !== undefined && | ||
error.metadata !== undefined | ||
); | ||
} | ||
|
||
describe('Bigtable/Errors', () => { | ||
let server: MockServer; | ||
let bigtable: Bigtable; | ||
let table: any; | ||
|
||
before(done => { | ||
server = new MockServer(() => { | ||
bigtable = new Bigtable({ | ||
apiEndpoint: `localhost:${server.port}`, | ||
}); | ||
table = bigtable.instance('fake-instance').table('fake-table'); | ||
done(); | ||
}); | ||
}); | ||
|
||
describe('with the bigtable data client', () => { | ||
let service: MockService; | ||
before(async () => { | ||
service = new BigtableClientMockService(server); | ||
}); | ||
|
||
describe('sends errors through a streaming request', () => { | ||
const errorDetails = | ||
'Table not found: projects/my-project/instances/my-instance/tables/my-table'; | ||
const emitTableNotExistsError = (stream: any) => { | ||
// TODO: Replace stream with type | ||
const metadata = new grpc.Metadata(); | ||
metadata.set( | ||
'grpc-server-stats-bin', | ||
Buffer.from([0, 0, 116, 73, 159, 3, 0, 0, 0, 0]) | ||
); | ||
stream.emit('error', { | ||
code: 5, | ||
details: errorDetails, | ||
metadata, | ||
}); | ||
}; | ||
function checkTableNotExistError(err: any) { | ||
if (isServiceError(err)) { | ||
const {code, message, details} = err; | ||
assert.strictEqual(details, errorDetails); | ||
assert.strictEqual(code, 5); | ||
assert.strictEqual(message, `5 NOT_FOUND: ${errorDetails}`); | ||
} else { | ||
assert.fail( | ||
'Errors checked using this function should all be GoogleErrors' | ||
); | ||
} | ||
} | ||
describe('with ReadRows service', () => { | ||
before(async () => { | ||
service.setService({ | ||
ReadRows: emitTableNotExistsError, | ||
}); | ||
}); | ||
it('should produce human readable error when passing through gax', done => { | ||
const readStream = table.createReadStream({}); | ||
readStream.on('error', (err: GoogleError) => { | ||
checkTableNotExistError(err); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
describe('with mutateRows service through insert', () => { | ||
before(async () => { | ||
service.setService({ | ||
mutateRows: emitTableNotExistsError, | ||
}); | ||
}); | ||
it('should produce human readable error when passing through gax', async () => { | ||
const timestamp = new Date(); | ||
const rowsToInsert = [ | ||
{ | ||
key: 'r2', | ||
data: { | ||
cf1: { | ||
c1: { | ||
value: 'test-value2', | ||
labels: [], | ||
timestamp, | ||
}, | ||
}, | ||
}, | ||
}, | ||
]; | ||
try { | ||
await table.insert(rowsToInsert); | ||
} catch (err) { | ||
checkTableNotExistError(err); | ||
return; | ||
} | ||
assert.fail('An error should have been thrown by the stream'); | ||
}); | ||
}); | ||
describe('with sampleRowKeys', () => { | ||
before(async () => { | ||
service.setService({ | ||
sampleRowKeys: emitTableNotExistsError, | ||
}); | ||
}); | ||
it('should produce human readable error when passing through gax', async () => { | ||
try { | ||
await table.sampleRowKeys({}); | ||
} catch (err) { | ||
checkTableNotExistError(err); | ||
return; | ||
} | ||
assert.fail('An error should have been thrown by the stream'); | ||
}); | ||
}); | ||
}); | ||
}); | ||
after(async () => { | ||
server.shutdown(() => {}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// Copyright 2022 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. | ||
// | ||
// ** This file is automatically generated by gapic-generator-typescript. ** | ||
// ** https://github.com/googleapis/gapic-generator-typescript ** | ||
// ** All changes to this file may be overwritten. ** | ||
|
||
import {describe, it} from 'mocha'; | ||
import {MockServer} from '../../src/util/mock-servers/mock-server'; | ||
import * as assert from 'assert'; | ||
|
||
const tcpPortUsed = require('tcp-port-used'); | ||
|
||
describe('Bigtable/Mock-Server', () => { | ||
const inputPort = '1234'; | ||
let server: MockServer; | ||
async function checkPort(port: string, inUse: boolean, callback: () => void) { | ||
const isInUse: boolean = await tcpPortUsed.check( | ||
parseInt(port), | ||
'localhost' | ||
); | ||
assert.strictEqual(isInUse, inUse); | ||
callback(); | ||
} | ||
describe('Ensure server shuts down properly when destroyed', () => { | ||
it('should start a mock server', done => { | ||
server = new MockServer(port => { | ||
checkPort(port, true, done); | ||
}, inputPort); | ||
}); | ||
}); | ||
after(done => { | ||
checkPort(server.port, true, () => { | ||
server.shutdown((err?: Error) => { | ||
assert.deepStrictEqual(err, undefined); | ||
checkPort(server.port, false, done); | ||
}); | ||
}); | ||
}); | ||
}); |