blob: 4ae95b0843d533cdd07f74e6f38cb0c1b844146a [file] [log] [blame]
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build fuchsia
package fidl_test
import (
"flag"
"fmt"
"math/rand"
"sync"
"syscall/zx"
"syscall/zx/fidl"
"syscall/zx/fidl/bindingstest"
"testing"
)
func init() { flag.CommandLine.Set("test.v", "true") }
var _ fidl.Message = (*message)(nil)
type message struct {
_ struct{} `fidl:"s,1,0" fidl2:"s,1,0"`
}
var _mMessage = fidl.MustCreateMarshaler(message{})
func (*message) Marshaler() fidl.Marshaler {
return _mMessage
}
func TestProxy(t *testing.T) {
const concurrency = 10
const numMessages = 100
c0, c1, err := zx.NewChannel(0)
if err != nil {
t.Fatal(err)
}
for _, proxies := range [][2]fidl.Proxy{
{&fidl.ChannelProxy{Channel: c0}, &fidl.ChannelProxy{Channel: c1}},
} {
sender, receiver := proxies[0], proxies[1]
t.Run(fmt.Sprintf("%T", sender), func(t *testing.T) {
var wg sync.WaitGroup
errs := make(chan error, concurrency)
// Spin up |concurrency| senders, each sending |numMessages|.
for i := 0; i < concurrency; i++ {
wg.Add(1)
go func() {
defer wg.Done()
errs <- func() error {
for i := 0; i < numMessages; i++ {
ordinal := rand.Uint64()
var resp message
if err := sender.Call(ordinal, &message{}, &resp); err != nil {
return err
}
}
return nil
}()
}()
}
//.Echo the |concurrency*numMessages| messages sent by the senders above.
for i := 0; i < concurrency*numMessages; i++ {
var respb [zx.ChannelMaxMessageBytes]byte
var msg []byte
switch receiver := receiver.(type) {
case *fidl.ChannelProxy:
if err := fidl.WithRetry(func() error {
nb, _, err := receiver.Channel.Read(respb[:], nil, 0)
if err == nil {
msg = respb[:nb]
}
return err
}, *receiver.Channel.Handle(), zx.SignalChannelReadable, zx.SignalChannelPeerClosed); err != nil {
t.Fatal(err)
}
default:
panic(fmt.Sprintf("unknown type %T", receiver))
}
var header fidl.MessageHeader
if _, _, err := fidl.Unmarshal(msg, nil, &header); err != nil {
t.Fatal(err)
}
cnb, _, err := fidl.MarshalHeaderThenMessage(&header, &message{}, respb[:], nil)
if err != nil {
t.Fatal(err)
}
switch receiver := receiver.(type) {
case *fidl.ChannelProxy:
if err := receiver.Channel.Write(respb[:cnb], nil, 0); err != nil {
t.Fatal(err)
}
default:
panic(fmt.Sprintf("unknown type %T", receiver))
}
}
wg.Wait()
close(errs)
for err := range errs {
if err != nil {
t.Error(err)
}
}
})
}
}
func TestMagicNumberSend(t *testing.T) {
ch, sh, err := zx.NewChannel(0)
if err != nil {
t.Fatal(err)
}
msg := bindingstest.TestSimple{X: 3}
client := fidl.ChannelProxy{Channel: ch}
if err := client.Send(0, &msg); err != nil {
t.Fatal(err)
}
respb := make([]byte, zx.ChannelMaxMessageBytes)
resph := make([]zx.Handle, zx.ChannelMaxMessageHandles)
nb, nh, err := sh.Read(respb[:], resph[:], 0)
if err != nil {
t.Fatal(err)
}
var header fidl.MessageHeader
if err = fidl.UnmarshalHeaderThenMessage(respb[:nb], resph[:nh], &header, &msg); err != nil {
t.Fatal(err)
}
if header.Magic != fidl.FidlWireFormatMagicNumberInitial {
t.Logf("expected client to send initial magic number")
t.Fatal(err)
}
}