/* * Copyright 2019 gRPC authors. * * 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. * */ // Allow `any` data type for testing runtime type checking. // tslint:disable no-any import * as assert from 'assert'; import * as path from 'path'; import * as grpc from '../src'; import { Server, ServerCredentials } from '../src'; import { ServiceError } from '../src/call'; import { ServiceClient, ServiceClientConstructor } from '../src/make-client'; import { sendUnaryData, ServerUnaryCall, ServerWritableStream, } from '../src/server-call'; import { loadProtoFile } from './common'; const clientInsecureCreds = grpc.credentials.createInsecure(); const serverInsecureCreds = ServerCredentials.createInsecure(); describe('Server deadlines', () => { let server: Server; let client: ServiceClient; before(done => { const protoFile = path.join(__dirname, 'fixtures', 'test_service.proto'); const testServiceDef = loadProtoFile(protoFile); const testServiceClient = testServiceDef.TestService as ServiceClientConstructor; server = new Server(); server.addService(testServiceClient.service, { unary(call: ServerUnaryCall, cb: sendUnaryData) { setTimeout(() => { cb(null, {}); }, 2000); }, }); server.bindAsync('localhost:0', serverInsecureCreds, (err, port) => { assert.ifError(err); client = new testServiceClient(`localhost:${port}`, clientInsecureCreds); server.start(); done(); }); }); after(done => { client.close(); server.tryShutdown(done); }); it('works with deadlines', done => { const metadata = new grpc.Metadata(); const { path, requestSerialize: serialize, responseDeserialize: deserialize, } = client.unary as any; metadata.set('grpc-timeout', '100m'); client.makeUnaryRequest( path, serialize, deserialize, {}, metadata, {}, (error: any, response: any) => { assert(error); assert.strictEqual(error.code, grpc.status.DEADLINE_EXCEEDED); assert.strictEqual(error.details, 'Deadline exceeded'); done(); } ); }); it('rejects invalid deadline', done => { const metadata = new grpc.Metadata(); const { path, requestSerialize: serialize, responseDeserialize: deserialize, } = client.unary as any; metadata.set('grpc-timeout', 'Infinity'); client.makeUnaryRequest( path, serialize, deserialize, {}, metadata, {}, (error: any, response: any) => { assert(error); assert.strictEqual(error.code, grpc.status.OUT_OF_RANGE); assert.strictEqual(error.details, 'Invalid deadline'); done(); } ); }); }); describe('Cancellation', () => { let server: Server; let client: ServiceClient; let inHandler = false; let cancelledInServer = false; before(done => { const protoFile = path.join(__dirname, 'fixtures', 'test_service.proto'); const testServiceDef = loadProtoFile(protoFile); const testServiceClient = testServiceDef.TestService as ServiceClientConstructor; server = new Server(); server.addService(testServiceClient.service, { serverStream(stream: ServerWritableStream) { inHandler = true; stream.on('cancelled', () => { stream.write({}); stream.end(); cancelledInServer = true; }); }, }); server.bindAsync('localhost:0', serverInsecureCreds, (err, port) => { assert.ifError(err); client = new testServiceClient(`localhost:${port}`, clientInsecureCreds); server.start(); done(); }); }); after(done => { client.close(); server.tryShutdown(done); }); it('handles requests cancelled by the client', done => { const call = client.serverStream({}); call.on('data', assert.ifError); call.on('error', (error: ServiceError) => { assert.strictEqual(error.code, grpc.status.CANCELLED); assert.strictEqual(error.details, 'Cancelled on client'); waitForServerCancel(); }); function waitForHandler() { if (inHandler === true) { call.cancel(); return; } setImmediate(waitForHandler); } function waitForServerCancel() { if (cancelledInServer === true) { done(); return; } setImmediate(waitForServerCancel); } waitForHandler(); }); });