go.nanomsg.org/mangos/v3@v3.4.3-0.20240217232803-46464076f1f5/protocol/bus/bus_test.go (about) 1 // Copyright 2019 The Mangos Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use file except in compliance with the License. 5 // You may obtain a copy of the license at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package bus 16 17 import ( 18 "encoding/binary" 19 "math/rand" 20 "sync" 21 "testing" 22 "time" 23 24 "go.nanomsg.org/mangos/v3" 25 . "go.nanomsg.org/mangos/v3/internal/test" 26 "go.nanomsg.org/mangos/v3/protocol/xbus" 27 _ "go.nanomsg.org/mangos/v3/transport/inproc" 28 ) 29 30 func TestBusIdentity(t *testing.T) { 31 s := GetSocket(t, NewSocket) 32 id := s.Info() 33 MustBeTrue(t, id.Self == mangos.ProtoBus) 34 MustBeTrue(t, id.Peer == mangos.ProtoBus) 35 MustBeTrue(t, id.SelfName == "bus") 36 MustBeTrue(t, id.PeerName == "bus") 37 MustSucceed(t, s.Close()) 38 } 39 40 func TestBusCooked(t *testing.T) { 41 VerifyCooked(t, NewSocket) 42 } 43 44 func TestBusOptions(t *testing.T) { 45 VerifyInvalidOption(t, NewSocket) 46 VerifyOptionQLen(t, NewSocket, mangos.OptionWriteQLen) 47 } 48 49 func TestBusClosed(t *testing.T) { 50 VerifyClosedSend(t, NewSocket) 51 VerifyClosedRecv(t, NewSocket) 52 VerifyClosedClose(t, NewSocket) 53 VerifyClosedDial(t, NewSocket) 54 VerifyClosedListen(t, NewSocket) 55 } 56 57 func TestBusDevice(t *testing.T) { 58 hops := 25 // number of devices 59 count := 10 60 61 var socks []mangos.Socket 62 63 head := GetSocket(t, NewSocket) 64 tail := GetSocket(t, NewSocket) 65 66 MustSucceed(t, head.SetOption(mangos.OptionRecvDeadline, time.Second)) 67 MustSucceed(t, tail.SetOption(mangos.OptionRecvDeadline, time.Second)) 68 69 socks = append(socks, head) 70 for i := 0; i < hops; i++ { 71 s1 := GetSocket(t, xbus.NewSocket) 72 s2 := GetSocket(t, xbus.NewSocket) 73 ConnectPair(t, socks[len(socks)-1], s1) 74 socks = append(socks, s1, s2) 75 go func() { _ = mangos.Device(s1, s2) }() 76 } 77 ConnectPair(t, socks[len(socks)-1], tail) 78 socks = append(socks, tail) 79 80 rng := rand.NewSource(32) 81 for i := 0; i < count; i++ { 82 var src, dst mangos.Socket 83 if rng.Int63()&1 != 0 { 84 src = head 85 dst = tail 86 } else { 87 src = tail 88 dst = head 89 } 90 msg := make([]byte, 4) 91 val := uint32(rng.Int63()) 92 binary.BigEndian.PutUint32(msg, val) 93 MustSucceed(t, src.Send(msg)) 94 res := MustRecv(t, dst) 95 MustBeTrue(t, len(res) == 4) 96 MustBeTrue(t, binary.BigEndian.Uint32(res) == val) 97 } 98 for _, s := range socks { 99 MustSucceed(t, s.Close()) 100 } 101 } 102 103 func TestBusFanOut(t *testing.T) { 104 count := 20 105 nPeers := 100 106 107 peers := make([]mangos.Socket, nPeers) 108 self := GetSocket(t, NewSocket) 109 MustSucceed(t, self.SetOption(mangos.OptionWriteQLen, count)) 110 111 for i := 0; i < nPeers; i++ { 112 peers[i] = GetSocket(t, NewSocket) 113 MustSucceed(t, peers[i].SetOption(mangos.OptionRecvDeadline, time.Second)) 114 ConnectPair(t, self, peers[i]) 115 } 116 117 wg := sync.WaitGroup{} 118 wg.Add(nPeers) 119 120 pass := make([]bool, nPeers) 121 for i := 0; i < nPeers; i++ { 122 go func(index int) { 123 defer wg.Done() 124 s := peers[index] 125 num := uint32(0) 126 for j := 0; j < count; j++ { 127 m := MustRecv(t, s) 128 MustBeTrue(t, len(m) == 4) 129 MustBeTrue(t, binary.BigEndian.Uint32(m) == num) 130 num++ 131 } 132 MustSucceed(t, s.SetOption(mangos.OptionRecvDeadline, 133 time.Millisecond*10)) 134 _, e := s.Recv() 135 MustBeError(t, e, mangos.ErrRecvTimeout) 136 pass[index] = true 137 }(i) 138 } 139 140 for i := 0; i < count; i++ { 141 msg := make([]byte, 4) 142 binary.BigEndian.PutUint32(msg, uint32(i)) 143 MustSucceed(t, self.Send(msg)) 144 } 145 146 wg.Wait() 147 for i := 0; i < count; i++ { 148 MustBeTrue(t, pass[i]) 149 MustSucceed(t, peers[i].Close()) 150 } 151 MustSucceed(t, self.Close()) 152 } 153 154 func TestBusFanIn(t *testing.T) { 155 count := 20 156 nPeers := 100 157 158 peers := make([]mangos.Socket, nPeers) 159 self := GetSocket(t, NewSocket) 160 MustSucceed(t, self.SetOption(mangos.OptionReadQLen, count*nPeers)) 161 MustSucceed(t, self.SetOption(mangos.OptionRecvDeadline, time.Second)) 162 163 for i := 0; i < nPeers; i++ { 164 peers[i] = GetSocket(t, NewSocket) 165 MustSucceed(t, self.SetOption(mangos.OptionWriteQLen, count)) 166 ConnectPair(t, self, peers[i]) 167 } 168 169 wg := sync.WaitGroup{} 170 wg.Add(nPeers) 171 172 for i := 0; i < nPeers; i++ { 173 go func(index int) { 174 defer wg.Done() 175 s := peers[index] 176 msg := make([]byte, 8) 177 binary.BigEndian.PutUint32(msg, uint32(index)) 178 num := uint32(0) 179 for j := 0; j < count; j++ { 180 binary.BigEndian.PutUint32(msg[4:], num) 181 MustSucceed(t, s.Send(msg)) 182 num++ 183 } 184 }(i) 185 } 186 187 counts := make([]uint32, nPeers) 188 for i := 0; i < count*nPeers; i++ { 189 m := MustRecv(t, self) 190 MustBeTrue(t, len(m) == 8) 191 index := binary.BigEndian.Uint32(m) 192 num := binary.BigEndian.Uint32(m[4:]) 193 MustBeTrue(t, index < uint32(nPeers)) 194 MustBeTrue(t, num == counts[index]) 195 MustBeTrue(t, num < uint32(count)) 196 counts[index]++ 197 } 198 MustSucceed(t, self.SetOption(mangos.OptionRecvDeadline, 199 time.Millisecond*10)) 200 _, e := self.Recv() 201 MustBeError(t, e, mangos.ErrRecvTimeout) 202 203 wg.Wait() 204 for i := 0; i < nPeers; i++ { 205 MustBeTrue(t, counts[i] == uint32(count)) 206 MustSucceed(t, peers[i].Close()) 207 } 208 MustSucceed(t, self.Close()) 209 } 210 211 func TestBusDiscardHeader(t *testing.T) { 212 self := GetSocket(t, NewSocket) 213 peer := GetSocket(t, NewSocket) 214 ConnectPair(t, self, peer) 215 216 m := mangos.NewMessage(0) 217 m.Header = append(m.Header, 0, 1, 2, 3) 218 m.Body = append(m.Body, []byte("abc")...) 219 MustSucceed(t, self.SendMsg(m)) 220 recv := MustRecvMsg(t, peer) 221 MustBeTrue(t, len(recv.Header) == 0) 222 MustBeTrue(t, string(recv.Body) == "abc") 223 MustSucceed(t, self.Close()) 224 MustSucceed(t, peer.Close()) 225 }