blob: a52139e902ca7f178150c2ad93f448f2d5542bfe [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package fidl_test
import (
"fmt"
"reflect"
"strings"
"syscall/zx"
"syscall/zx/fidl"
"syscall/zx/fidl/internal/bindingstest"
"testing"
)
var testCtx fidl.MarshalerContext
type example struct {
name string
input fidl.Message
expectSize int
}
// general provides test cases used to verify correctness, and
// benchmark against.
//
// Keep these as a slice to preserve consistent ordering when running.
func general() []example {
h0, h1, err := zx.NewChannel(0)
if err != nil {
panic(fmt.Sprintf("failed to create channel: %s", err))
}
defer func() {
if err := h0.Close(); err != nil {
panic(fmt.Sprintf("failed to close channel: %s", err))
}
if err := h1.Close(); err != nil {
panic(fmt.Sprintf("failed to close channel: %s", err))
}
}()
return []example{
// TODO(https://fxbug.dev/42158433): Here we're checking the special logic adapting channels to
// `request<P>` or `P` representations. This is not supported by GIDL yet.
{"interface1", &bindingstest.TestInterface1{
A: bindingstest.Test1WithCtxInterface(fidl.ChannelProxy{Channel: h0}),
B: bindingstest.Test1WithCtxInterface(fidl.ChannelProxy{Channel: zx.Channel(zx.HandleInvalid)}),
C: bindingstest.Test1WithCtxInterfaceRequest(fidl.InterfaceRequest{Channel: h1}),
D: bindingstest.Test1WithCtxInterfaceRequest(fidl.InterfaceRequest{
Channel: zx.Channel(zx.HandleInvalid),
}),
}, 16},
}
}
func check(t *testing.T, input fidl.Message, expectSize int) {
t.Helper()
var respb [zx.ChannelMaxMessageBytes]byte
var resphd [zx.ChannelMaxMessageHandles]zx.HandleDisposition
nb, nh, err := fidl.Marshal(testCtx, input, respb[:], resphd[:])
if err != nil {
t.Fatalf("marshal: failed: %s", err)
}
if nb != expectSize {
t.Fatalf("marshal: expected size %d but got %d: %s", expectSize, nb, respb[:nb])
}
var resphi [zx.ChannelMaxMessageHandles]zx.HandleInfo
for i := 0; i < nh; i++ {
resphi[i] = zx.HandleInfo{
Handle: resphd[i].Handle,
Type: resphd[i].Type,
Rights: resphd[i].Rights,
}
}
output := makeDefault(reflect.TypeOf(input))
err = fidl.Unmarshal(testCtx, respb[:nb], resphi[:nh], output)
if err != nil {
t.Fatalf("unmarshal: failed: %s", err)
}
if !reflect.DeepEqual(input, output) {
t.Fatalf("unmarshal: expected: %#v, got: %#v", input, output)
}
}
func TestCorrectness(t *testing.T) {
for _, ex := range general() {
t.Run(ex.name, func(t *testing.T) {
check(t, ex.input, ex.expectSize)
})
}
}
// This is a specific test checking that the marshaler construction properly
// fails with a clear error message if fed incorrect generated code. Hence,
// this has to stay a hand written test.
func TestFailureNullableTable(t *testing.T) {
type TestNullableTable struct {
_ struct{} `fidl:"s"`
A *bindingstest.SimpleTable `fidl:"0" fidl_offset_v2:"0"`
}
_, err := fidl.CreateMarshaler(TestNullableTable{})
if err == nil {
t.Fatalf("expected error creating marshaler for nullable table")
}
if !strings.Contains(err.Error(), "optional field marshaler") {
t.Fatalf("unexpected error: %s", err.Error())
}
}
// TODO(https://fxbug.dev/42141063): Move to GIDL once we support protocol handles.
func TestConformanceClientEnd(t *testing.T) {
successCase{
name: "handles-clientend",
context: testCtx,
input: &bindingstest.HasClientEnd{
ClientEnd: bindingstest.ExampleProtocolWithCtxInterface(fidl.ChannelProxy{
Channel: zx.Channel(0x44332211),
}),
},
bytes: []byte{
0xff, 0xff, 0xff, 0xff, // handle present
0x00, 0x00, 0x00, 0x00, // padding
},
handleInfos: []zx.HandleInfo{
{
Handle: zx.Handle(0x44332211),
Rights: fidl.ProtocolRights,
Type: zx.ObjTypeChannel,
},
},
checkRights: true,
}.check(t)
}
// TODO(https://fxbug.dev/42141063): Move to GIDL once we support protocol handles.
func TestConformanceServerEnd(t *testing.T) {
successCase{
name: "handles-serverend",
context: testCtx,
input: &bindingstest.HasServerEnd{
ServerEnd: bindingstest.ExampleProtocolWithCtxInterfaceRequest(fidl.InterfaceRequest{
Channel: zx.Channel(0x44332211),
}),
},
bytes: []byte{
0xff, 0xff, 0xff, 0xff, // handle present
0x00, 0x00, 0x00, 0x00, // padding
},
handleInfos: []zx.HandleInfo{
{
Handle: zx.Handle(0x44332211),
Rights: fidl.ProtocolRights,
Type: zx.ObjTypeChannel,
},
},
checkRights: true,
}.check(t)
}