blob: 872b9ffddee0c477e982eae58a8df04de6421573 [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 (
"fmt"
"math/rand"
"sync"
"syscall/zx"
"syscall/zx/fidl"
"testing"
)
var _ fidl.Message = (*message)(nil)
type message struct {
_ struct{} `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)
}
s0, s1, err := zx.NewSocket(zx.SocketHasControl)
if err != nil {
t.Fatal(err)
}
for _, proxies := range [][2]fidl.Proxy{
{&fidl.ChannelProxy{Channel: c0}, &fidl.ChannelProxy{Channel: c1}},
{&fidl.SocketControlProxy{Socket: s0}, &fidl.SocketControlProxy{Socket: s1}},
} {
sender, receiver := proxies[0], proxies[1]
t.Run(fmt.Sprintf("%T", sender), func(t *testing.T) {
if _, ok := sender.(*fidl.SocketControlProxy); ok {
t.Skip("See NET-2364 & FLK-422")
}
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)
}
case *fidl.SocketControlProxy:
if err := fidl.WithRetry(func() error {
nb, err := receiver.Socket.Read(respb[:], zx.SocketControl)
if err == nil {
msg = respb[:nb]
}
return err
}, *receiver.Socket.Handle(), zx.SignalSocketControlReadable, zx.SignalSocketPeerClosed); 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)
}
case *fidl.SocketControlProxy:
if _, err := receiver.Socket.Write(respb[:cnb], zx.SocketControl); 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)
}
}
})
}
}