// Copyright 2021 The Pigweed 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 // // 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. /* eslint-env browser, jasmine */ import 'jasmine'; import {SomeMessage} from 'test_protos_tspb/test_protos_tspb_pb/pw_rpc/ts/test2_pb'; import {Call} from './call'; import {Channel, Method, Service} from './descriptors'; import {PendingCalls, Rpc} from './rpc_classes'; class FakeRpc { readonly channel: any = undefined; readonly service: any = undefined; readonly method: any = undefined; idSet: [number, number, number] = [1, 2, 3]; idString = '1.2.3'; } describe('Call', () => { let call: Call; beforeEach(() => { const noop = () => {}; const pendingCalls = new PendingCalls(); const channel = jasmine.createSpy(); const rpc = new FakeRpc(); call = new Call(pendingCalls, rpc, noop, noop, noop); }); function newMessage(magicNumber = 1): SomeMessage { const message = new SomeMessage(); message.setMagicNumber(magicNumber); return message; } it('getResponse returns all responses.', async () => { const message1 = newMessage(1); const message2 = newMessage(2); const message3 = newMessage(3); // Queue three responses call.handleResponse(message1); call.handleResponse(message2); call.handleResponse(message3); let responses = call.getResponses(2); expect((await responses.next()).value).toEqual(message1); expect((await responses.next()).value).toEqual(message2); expect((await responses.next()).done).toBeTrue(); responses = call.getResponses(1); expect((await responses.next()).value).toEqual(message3); expect((await responses.next()).done).toBeTrue(); }); it('getResponse early returns on stream end.', async () => { const message = newMessage(); const responses = call.getResponses(2); // Queue one response and an early completion. call.handleResponse(message); call.handleCompletion(0); expect((await responses.next()).value).toEqual(message); expect((await responses.next()).done).toBeTrue(); }); it('getResponse promise is rejected on stream error.', async () => { const message = newMessage(); const responses = call.getResponses(3); call.handleResponse(message); expect((await responses.next()).value).toEqual(message); call.handleResponse(message); call.handleError(1); // Promise is rejected as soon as an error is received, even if there is a // response in the queue. await expectAsync(responses.next()).toBeRejected(); }); it('getResponse waits if queue is empty', async () => { const message1 = newMessage(1); const message2 = newMessage(2); const responses = call.getResponses(2); // Queue two responses after a small delay setTimeout(() => { call.handleResponse(message1); call.handleResponse(message2); call.handleCompletion(0); expect(call.completed).toBeTrue(); }, 200); expect(call.completed).toBeFalse(); expect((await responses.next()).value).toEqual(message1); expect((await responses.next()).value).toEqual(message2); expect((await responses.next()).done).toBeTrue(); }); it('getResponse without count fetches all results', async () => { const message1 = newMessage(1); const message2 = newMessage(2); const responses = call.getResponses(); call.handleResponse(message1); expect((await responses.next()).value).toEqual(message1); setTimeout(() => { call.handleResponse(message2); call.handleCompletion(0); expect(call.completed).toBeTrue(); }, 200); expect(call.completed).toBeFalse(); expect((await responses.next()).value).toEqual(message2); expect((await responses.next()).done).toBeTrue(); }); });