blob: 47af6dab849df4a7987cab212080b6ca598c0592 [file] [log] [blame]
// Copyright 2022 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 */
import {SomeMessage} from 'pigweedjs/protos/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 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).toEqual(true);
responses = call.getResponses(1);
expect((await responses.next()).value).toEqual(message3);
expect((await responses.next()).done).toEqual(true);
});
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).toEqual(true);
});
it('getResponse promise is rejected on stream error.', async () => {
expect.assertions(2);
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.
responses.next().catch((e: Error) => {
expect(e.name).toEqual('TypeError');
});
});
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).toEqual(true);
}, 200);
expect(call.completed).toEqual(false);
expect((await responses.next()).value).toEqual(message1);
expect((await responses.next()).value).toEqual(message2);
expect((await responses.next()).done).toEqual(true);
});
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).toEqual(true);
}, 200);
expect(call.completed).toEqual(false);
expect((await responses.next()).value).toEqual(message2);
expect((await responses.next()).done).toEqual(true);
});
});