| // 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 {SerialMock} from '../transport/serial_mock'; |
| import {Device} from "./" |
| import {ProtoCollection} from 'pigweedjs/protos/collection'; |
| import {WebSerialTransport} from '../transport/web_serial_transport'; |
| import {Serial} from 'pigweedjs/types/serial'; |
| import {Message} from 'google-protobuf'; |
| import {RpcPacket, PacketType} from 'pigweedjs/protos/pw_rpc/internal/packet_pb'; |
| import {Method, ServerStreamingMethodStub} from 'pigweedjs/pw_rpc'; |
| import {Status} from 'pigweedjs/pw_status'; |
| import { |
| Response, |
| } from 'pigweedjs/protos/pw_rpc/ts/test_pb'; |
| |
| describe('WebSerialTransport', () => { |
| let device: Device; |
| let serialMock: SerialMock; |
| |
| function newResponse(payload = '._.'): Message { |
| const response = new Response(); |
| response.setPayload(payload); |
| return response; |
| } |
| |
| function generateResponsePacket( |
| channelId: number, |
| method: Method, |
| status: Status, |
| response?: Message |
| ) { |
| const packet = new RpcPacket(); |
| packet.setType(PacketType.RESPONSE); |
| packet.setChannelId(channelId); |
| packet.setServiceId(method.service.id); |
| packet.setMethodId(method.id); |
| packet.setStatus(status); |
| if (response === undefined) { |
| packet.setPayload(new Uint8Array()); |
| } else { |
| packet.setPayload(response.serializeBinary()); |
| } |
| return packet.serializeBinary(); |
| } |
| |
| function generateStreamingPacket( |
| channelId: number, |
| method: Method, |
| response: Message, |
| status: Status = Status.OK |
| ) { |
| const packet = new RpcPacket(); |
| packet.setType(PacketType.SERVER_STREAM); |
| packet.setChannelId(channelId); |
| packet.setServiceId(method.service.id); |
| packet.setMethodId(method.id); |
| packet.setPayload(response.serializeBinary()); |
| packet.setStatus(status); |
| return packet.serializeBinary(); |
| } |
| |
| beforeEach(() => { |
| serialMock = new SerialMock(); |
| device = new Device(new ProtoCollection(), new WebSerialTransport(serialMock as Serial)); |
| }); |
| |
| it('has rpcs defined', () => { |
| expect(device.rpcs).toBeDefined(); |
| expect(device.rpcs.pw.rpc.EchoService.Echo).toBeDefined(); |
| }); |
| |
| it('has method arguments data', () => { |
| expect(device.getMethodArguments("pw.rpc.EchoService.Echo")).toStrictEqual(["msg"]); |
| expect(device.getMethodArguments("pw.test2.Alpha.Unary")).toStrictEqual(['magic_number']); |
| }); |
| |
| it('unary rpc sends request to serial', async () => { |
| const helloResponse = new Uint8Array([ |
| 126, 165, 3, 42, 7, 10, 5, 104, |
| 101, 108, 108, 111, 8, 1, 16, 1, |
| 29, 82, 208, 251, 20, 37, 233, 14, |
| 71, 139, 109, 127, 108, 165, 126]); |
| |
| await device.connect(); |
| serialMock.dataFromDevice(helloResponse); |
| const [status, response] = await device.rpcs.pw.rpc.EchoService.Echo("hello"); |
| expect(response.getMsg()).toBe("hello"); |
| expect(status).toBe(0); |
| }); |
| |
| it('server streaming rpc sends response', async () => { |
| await device.connect(); |
| const response1 = newResponse('!!!'); |
| const response2 = newResponse('?'); |
| const serverStreaming = device.client |
| .channel() |
| ?.methodStub( |
| 'pw.rpc.test1.TheTestService.SomeServerStreaming' |
| )! as ServerStreamingMethodStub; |
| const onNext = jest.fn(); |
| const onCompleted = jest.fn(); |
| const onError = jest.fn(); |
| |
| device.rpcs.pw.rpc.test1.TheTestService.SomeServerStreaming(4, onNext, onCompleted, onError); |
| device.client.processPacket(generateStreamingPacket(1, serverStreaming.method, response1)); |
| device.client.processPacket(generateStreamingPacket(1, serverStreaming.method, response2)); |
| device.client.processPacket(generateResponsePacket(1, serverStreaming.method, Status.ABORTED)); |
| |
| expect(onNext).toBeCalledWith(response1); |
| expect(onNext).toBeCalledWith(response2); |
| expect(onCompleted).toBeCalledWith(Status.ABORTED); |
| }); |
| }); |