xref: /aosp_15_r20/external/pigweed/ts/device/index_test.ts (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker// Copyright 2022 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker//
3*61c4878aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker// use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker// the License at
6*61c4878aSAndroid Build Coastguard Worker//
7*61c4878aSAndroid Build Coastguard Worker//     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker//
9*61c4878aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker// License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker// the License.
14*61c4878aSAndroid Build Coastguard Worker
15*61c4878aSAndroid Build Coastguard Worker/* eslint-env browser */
16*61c4878aSAndroid Build Coastguard Workerimport { SerialMock } from '../transport/serial_mock';
17*61c4878aSAndroid Build Coastguard Workerimport { Device } from './';
18*61c4878aSAndroid Build Coastguard Workerimport { ProtoCollection } from 'pigweedjs/protos/collection';
19*61c4878aSAndroid Build Coastguard Workerimport { WebSerialTransport } from '../transport/web_serial_transport';
20*61c4878aSAndroid Build Coastguard Workerimport { Serial } from 'pigweedjs/types/serial';
21*61c4878aSAndroid Build Coastguard Workerimport { Message } from 'google-protobuf';
22*61c4878aSAndroid Build Coastguard Workerimport {
23*61c4878aSAndroid Build Coastguard Worker  RpcPacket,
24*61c4878aSAndroid Build Coastguard Worker  PacketType,
25*61c4878aSAndroid Build Coastguard Worker} from 'pigweedjs/protos/pw_rpc/internal/packet_pb';
26*61c4878aSAndroid Build Coastguard Workerimport {
27*61c4878aSAndroid Build Coastguard Worker  Method,
28*61c4878aSAndroid Build Coastguard Worker  ServerStreamingMethodStub,
29*61c4878aSAndroid Build Coastguard Worker  UnaryMethodStub,
30*61c4878aSAndroid Build Coastguard Worker} from 'pigweedjs/pw_rpc';
31*61c4878aSAndroid Build Coastguard Workerimport { Status } from 'pigweedjs/pw_status';
32*61c4878aSAndroid Build Coastguard Workerimport { Response } from 'pigweedjs/protos/pw_rpc/ts/test_pb';
33*61c4878aSAndroid Build Coastguard Worker
34*61c4878aSAndroid Build Coastguard Workerdescribe('WebSerialTransport', () => {
35*61c4878aSAndroid Build Coastguard Worker  let device: Device;
36*61c4878aSAndroid Build Coastguard Worker  let serialMock: SerialMock;
37*61c4878aSAndroid Build Coastguard Worker
38*61c4878aSAndroid Build Coastguard Worker  function newResponse(payload = '._.'): Message {
39*61c4878aSAndroid Build Coastguard Worker    const response = new Response();
40*61c4878aSAndroid Build Coastguard Worker    response.setPayload(payload);
41*61c4878aSAndroid Build Coastguard Worker    return response;
42*61c4878aSAndroid Build Coastguard Worker  }
43*61c4878aSAndroid Build Coastguard Worker
44*61c4878aSAndroid Build Coastguard Worker  function generateResponsePacket(
45*61c4878aSAndroid Build Coastguard Worker    channelId: number,
46*61c4878aSAndroid Build Coastguard Worker    method: Method,
47*61c4878aSAndroid Build Coastguard Worker    status: Status,
48*61c4878aSAndroid Build Coastguard Worker    callId: number,
49*61c4878aSAndroid Build Coastguard Worker    response?: Message,
50*61c4878aSAndroid Build Coastguard Worker  ) {
51*61c4878aSAndroid Build Coastguard Worker    const packet = new RpcPacket();
52*61c4878aSAndroid Build Coastguard Worker    packet.setType(PacketType.RESPONSE);
53*61c4878aSAndroid Build Coastguard Worker    packet.setChannelId(channelId);
54*61c4878aSAndroid Build Coastguard Worker    packet.setServiceId(method.service.id);
55*61c4878aSAndroid Build Coastguard Worker    packet.setMethodId(method.id);
56*61c4878aSAndroid Build Coastguard Worker    packet.setCallId(callId);
57*61c4878aSAndroid Build Coastguard Worker    packet.setStatus(status);
58*61c4878aSAndroid Build Coastguard Worker    if (response === undefined) {
59*61c4878aSAndroid Build Coastguard Worker      packet.setPayload(new Uint8Array(0));
60*61c4878aSAndroid Build Coastguard Worker    } else {
61*61c4878aSAndroid Build Coastguard Worker      packet.setPayload(response.serializeBinary());
62*61c4878aSAndroid Build Coastguard Worker    }
63*61c4878aSAndroid Build Coastguard Worker    return packet.serializeBinary();
64*61c4878aSAndroid Build Coastguard Worker  }
65*61c4878aSAndroid Build Coastguard Worker
66*61c4878aSAndroid Build Coastguard Worker  function generateStreamingPacket(
67*61c4878aSAndroid Build Coastguard Worker    channelId: number,
68*61c4878aSAndroid Build Coastguard Worker    method: Method,
69*61c4878aSAndroid Build Coastguard Worker    response: Message,
70*61c4878aSAndroid Build Coastguard Worker    callId: number,
71*61c4878aSAndroid Build Coastguard Worker    status: Status = Status.OK,
72*61c4878aSAndroid Build Coastguard Worker  ) {
73*61c4878aSAndroid Build Coastguard Worker    const packet = new RpcPacket();
74*61c4878aSAndroid Build Coastguard Worker    packet.setType(PacketType.SERVER_STREAM);
75*61c4878aSAndroid Build Coastguard Worker    packet.setChannelId(channelId);
76*61c4878aSAndroid Build Coastguard Worker    packet.setServiceId(method.service.id);
77*61c4878aSAndroid Build Coastguard Worker    packet.setMethodId(method.id);
78*61c4878aSAndroid Build Coastguard Worker    packet.setCallId(callId);
79*61c4878aSAndroid Build Coastguard Worker    packet.setPayload(response.serializeBinary());
80*61c4878aSAndroid Build Coastguard Worker    packet.setStatus(status);
81*61c4878aSAndroid Build Coastguard Worker    return packet.serializeBinary();
82*61c4878aSAndroid Build Coastguard Worker  }
83*61c4878aSAndroid Build Coastguard Worker
84*61c4878aSAndroid Build Coastguard Worker  beforeEach(() => {
85*61c4878aSAndroid Build Coastguard Worker    serialMock = new SerialMock();
86*61c4878aSAndroid Build Coastguard Worker    device = new Device(
87*61c4878aSAndroid Build Coastguard Worker      new ProtoCollection(),
88*61c4878aSAndroid Build Coastguard Worker      new WebSerialTransport(serialMock as Serial),
89*61c4878aSAndroid Build Coastguard Worker    );
90*61c4878aSAndroid Build Coastguard Worker  });
91*61c4878aSAndroid Build Coastguard Worker
92*61c4878aSAndroid Build Coastguard Worker  it('has rpcs defined', () => {
93*61c4878aSAndroid Build Coastguard Worker    expect(device.rpcs).toBeDefined();
94*61c4878aSAndroid Build Coastguard Worker    expect(device.rpcs.pw.rpc.EchoService.Echo).toBeDefined();
95*61c4878aSAndroid Build Coastguard Worker  });
96*61c4878aSAndroid Build Coastguard Worker
97*61c4878aSAndroid Build Coastguard Worker  it('unary rpc sends request to serial', async () => {
98*61c4878aSAndroid Build Coastguard Worker    const methodStub = device.client
99*61c4878aSAndroid Build Coastguard Worker      .channel()!
100*61c4878aSAndroid Build Coastguard Worker      .methodStub('pw.rpc.EchoService.Echo')! as UnaryMethodStub;
101*61c4878aSAndroid Build Coastguard Worker    const req = device.rpcs.pw.rpc.EchoService.Echo.createRequest();
102*61c4878aSAndroid Build Coastguard Worker    req.setMsg('hello');
103*61c4878aSAndroid Build Coastguard Worker    await device.connect();
104*61c4878aSAndroid Build Coastguard Worker    const nextCallId = methodStub.rpcs.nextCallId;
105*61c4878aSAndroid Build Coastguard Worker    setTimeout(() => {
106*61c4878aSAndroid Build Coastguard Worker      device.client.processPacket(
107*61c4878aSAndroid Build Coastguard Worker        generateResponsePacket(
108*61c4878aSAndroid Build Coastguard Worker          1,
109*61c4878aSAndroid Build Coastguard Worker          methodStub.method,
110*61c4878aSAndroid Build Coastguard Worker          Status.OK,
111*61c4878aSAndroid Build Coastguard Worker          nextCallId,
112*61c4878aSAndroid Build Coastguard Worker          req,
113*61c4878aSAndroid Build Coastguard Worker        ),
114*61c4878aSAndroid Build Coastguard Worker      );
115*61c4878aSAndroid Build Coastguard Worker    }, 10);
116*61c4878aSAndroid Build Coastguard Worker
117*61c4878aSAndroid Build Coastguard Worker    const [status, response] =
118*61c4878aSAndroid Build Coastguard Worker      await device.rpcs.pw.rpc.EchoService.Echo.call(req);
119*61c4878aSAndroid Build Coastguard Worker    expect(response.getMsg()).toBe('hello');
120*61c4878aSAndroid Build Coastguard Worker    expect(status).toBe(0);
121*61c4878aSAndroid Build Coastguard Worker  });
122*61c4878aSAndroid Build Coastguard Worker
123*61c4878aSAndroid Build Coastguard Worker  it('server streaming rpc sends response', async () => {
124*61c4878aSAndroid Build Coastguard Worker    await device.connect();
125*61c4878aSAndroid Build Coastguard Worker    const response1 = newResponse('!!!');
126*61c4878aSAndroid Build Coastguard Worker    const response2 = newResponse('?');
127*61c4878aSAndroid Build Coastguard Worker    const serverStreaming = device.client
128*61c4878aSAndroid Build Coastguard Worker      .channel()
129*61c4878aSAndroid Build Coastguard Worker      ?.methodStub(
130*61c4878aSAndroid Build Coastguard Worker        'pw.rpc.test1.TheTestService.SomeServerStreaming',
131*61c4878aSAndroid Build Coastguard Worker      ) as ServerStreamingMethodStub;
132*61c4878aSAndroid Build Coastguard Worker    const nextCallId = serverStreaming.rpcs.nextCallId;
133*61c4878aSAndroid Build Coastguard Worker    const onNext = jest.fn();
134*61c4878aSAndroid Build Coastguard Worker    const onCompleted = jest.fn();
135*61c4878aSAndroid Build Coastguard Worker    const onError = jest.fn();
136*61c4878aSAndroid Build Coastguard Worker
137*61c4878aSAndroid Build Coastguard Worker    const req =
138*61c4878aSAndroid Build Coastguard Worker      device.rpcs.pw.rpc.test1.TheTestService.SomeServerStreaming.createRequest();
139*61c4878aSAndroid Build Coastguard Worker    req.setMagicNumber(4);
140*61c4878aSAndroid Build Coastguard Worker    const rpcCall =
141*61c4878aSAndroid Build Coastguard Worker      device.rpcs.pw.rpc.test1.TheTestService.SomeServerStreaming.call(req);
142*61c4878aSAndroid Build Coastguard Worker    device.client.processPacket(
143*61c4878aSAndroid Build Coastguard Worker      generateStreamingPacket(1, serverStreaming.method, response1, nextCallId),
144*61c4878aSAndroid Build Coastguard Worker    );
145*61c4878aSAndroid Build Coastguard Worker    device.client.processPacket(
146*61c4878aSAndroid Build Coastguard Worker      generateStreamingPacket(1, serverStreaming.method, response2, nextCallId),
147*61c4878aSAndroid Build Coastguard Worker    );
148*61c4878aSAndroid Build Coastguard Worker    device.client.processPacket(
149*61c4878aSAndroid Build Coastguard Worker      generateResponsePacket(
150*61c4878aSAndroid Build Coastguard Worker        1,
151*61c4878aSAndroid Build Coastguard Worker        serverStreaming.method,
152*61c4878aSAndroid Build Coastguard Worker        Status.ABORTED,
153*61c4878aSAndroid Build Coastguard Worker        nextCallId,
154*61c4878aSAndroid Build Coastguard Worker      ),
155*61c4878aSAndroid Build Coastguard Worker    );
156*61c4878aSAndroid Build Coastguard Worker
157*61c4878aSAndroid Build Coastguard Worker    for await (const msg of rpcCall) {
158*61c4878aSAndroid Build Coastguard Worker      onNext(msg);
159*61c4878aSAndroid Build Coastguard Worker    }
160*61c4878aSAndroid Build Coastguard Worker
161*61c4878aSAndroid Build Coastguard Worker    onCompleted(rpcCall.call.status);
162*61c4878aSAndroid Build Coastguard Worker
163*61c4878aSAndroid Build Coastguard Worker    expect(onNext).toBeCalledWith(response1);
164*61c4878aSAndroid Build Coastguard Worker    expect(onNext).toBeCalledWith(response2);
165*61c4878aSAndroid Build Coastguard Worker    expect(onCompleted).toBeCalledWith(Status.ABORTED);
166*61c4878aSAndroid Build Coastguard Worker  });
167*61c4878aSAndroid Build Coastguard Worker});
168