| // 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) |
| } |
| } |