blob: 6b0406ab77a24b13ff13611045ceada282843377 [file] [log] [blame]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package ui
import (
"context"
"time"
"github.com/golang/protobuf/ptypes/empty"
"github.com/google/go-cmp/cmp"
"google.golang.org/grpc"
"google.golang.org/protobuf/testing/protocmp"
"google.golang.org/protobuf/types/known/structpb"
"go.chromium.org/tast-tests/cros/remote/crosserverutil"
pb "go.chromium.org/tast-tests/cros/services/cros/ui"
"go.chromium.org/tast/core/testing"
)
func init() {
testing.AddTest(&testing.Test{
Func: ConnServiceGRPC,
Desc: "Check basic functionalities of UI ConnService",
Contacts: []string{"lacros-team@google.com", "ythjkt@google.com"},
BugComponent: "b:1103568", // ChromeOS -> EngProd -> Developer
Attr: []string{"group:mainline", "informational", "group:hw_agnostic"},
SoftwareDeps: []string{"chrome"},
LacrosStatus: testing.LacrosVariantUnneeded,
Timeout: time.Minute * 5,
})
}
// ConnServiceGRPC tests basic functionalities of UI ConnService.
func ConnServiceGRPC(ctx context.Context, s *testing.State) {
cl, err := crosserverutil.GetGRPCClient(ctx, s.DUT())
if err != nil {
s.Fatal("Failed to connect to the RPC service on the DUT: ", err)
}
defer cl.Close(ctx)
// Start Chrome on the DUT.
cs := pb.NewChromeServiceClient(cl.Conn)
loginReq := &pb.NewRequest{}
if _, err := cs.New(ctx, loginReq, grpc.WaitForReady(true)); err != nil {
s.Fatal("Failed to start Chrome: ", err)
}
defer cs.Close(ctx, &empty.Empty{})
svc := pb.NewConnServiceClient(cl.Conn)
defer svc.CloseAll(ctx, &empty.Empty{})
value := func(val interface{}) *structpb.Value {
result, err := structpb.NewValue(val)
if err != nil {
s.Fatal("Invalid value: ", err)
}
return result
}
undefined := &structpb.Value{}
if cmp.Equal(value(nil), undefined, protocmp.Transform()) {
s.Fatal("Nil and undefined are indistinguishable")
}
got, err := svc.NewConn(ctx, &pb.NewConnRequest{Url: "about:blank"})
if err != nil {
s.Fatal("Failed to open \"about:blank\" page")
}
id := got.Id
structValue := value(map[string]interface{}{"a": 1, "b": 2})
for _, tc := range []struct {
expr string
want *structpb.Value
}{
{
expr: "null",
want: value(nil),
},
{
expr: "undefined",
want: undefined,
},
{
expr: "1 + 1",
want: value(2),
},
{
expr: "(() => { return {a: 1, b: 2} })()",
want: structValue,
},
} {
got, err := svc.Eval(ctx, &pb.ConnEvalRequest{Id: id, Expr: tc.expr})
if err != nil {
s.Fatalf("Eval(%s) failed: %v", tc.expr, err)
}
if diff := cmp.Diff(got, tc.want, protocmp.Transform()); diff != "" {
s.Fatalf("Eval(%s) mismatch (-got +want):%s", tc.expr, diff)
}
}
for _, tc := range []struct {
fn string
args []*structpb.Value
want *structpb.Value
}{
{
fn: "() => { return null; }",
args: []*structpb.Value{},
want: value(nil),
},
{
fn: "() => {}",
args: []*structpb.Value{},
want: undefined,
},
{
fn: "(x, y) => { return x + y; }",
args: []*structpb.Value{value(1), value(2)},
want: value(3),
},
{
fn: "(x) => { return x; }",
args: []*structpb.Value{structValue},
want: structValue,
},
} {
got, err := svc.Call(ctx, &pb.ConnCallRequest{Id: id, Fn: tc.fn, Args: tc.args})
if err != nil {
s.Fatalf("Call %s with args %v failed: %v", tc.fn, tc.args, err)
}
if diff := cmp.Diff(got, tc.want, protocmp.Transform()); diff != "" {
s.Fatalf("Call %s with args %v mismatch (-got +want):%s", tc.fn, tc.args, diff)
}
}
}