func TestDeviceBadPair(t *testing.T) { s1, err := req.NewSocket() if err != nil { t.Errorf("Failed to open S1: %v", err) return } defer s1.Close() s2, err := pair.NewSocket() if err != nil { t.Errorf("Failed to open S2: %v", err) return } defer s2.Close() switch err := mangos.Device(s1, s2); err { case mangos.ErrBadProto: t.Logf("Got expected err: %v", err) return case nil: t.Errorf("Matching incompatible types succeeded") return default: t.Errorf("Got unexpected err: %v", err) return } }
func testDevLoop(t *testing.T, addr string) { s1, err := pair.NewSocket() if err != nil { t.Errorf("Failed to open S1: %v", err) return } defer s1.Close() s1.AddTransport(tcp.NewTransport()) s1.AddTransport(inproc.NewTransport()) s1.AddTransport(ipc.NewTransport()) s1.AddTransport(tlstcp.NewTransport()) s1.AddTransport(ws.NewTransport()) s1.AddTransport(wss.NewTransport()) options := make(map[string]interface{}) if strings.HasPrefix(addr, "wss://") || strings.HasPrefix(addr, "tls+tcp://") { options[mangos.OptionTLSConfig] = srvCfg } if err := s1.ListenOptions(addr, options); err != nil { t.Errorf("Failed listening to %s: %v", addr, err) return } if err := mangos.Device(s1, s1); err != nil { t.Errorf("Device failed: %v", err) return } RunTests(t, addr, deviceCaseClient()) }
// NewSocket allocates a new Socket. The Socket is the handle used to // access the underlying library. func NewSocket(d Domain, p Protocol) (*Socket, error) { var s Socket var err error s.proto = p s.dom = d switch p { case PUB: s.sock, err = pub.NewSocket() case SUB: s.sock, err = sub.NewSocket() case PUSH: s.sock, err = push.NewSocket() case PULL: s.sock, err = pull.NewSocket() case REQ: s.sock, err = req.NewSocket() case REP: s.sock, err = rep.NewSocket() case SURVEYOR: s.sock, err = surveyor.NewSocket() case RESPONDENT: s.sock, err = respondent.NewSocket() case PAIR: s.sock, err = pair.NewSocket() case BUS: s.sock, err = bus.NewSocket() default: err = mangos.ErrBadProto } if err != nil { return nil, err } switch d { case AF_SP: case AF_SP_RAW: err = s.sock.SetOption(mangos.OptionRaw, true) default: err = errBadDomain } if err != nil { s.sock.Close() return nil, err } // Compat mode sockets should timeout on send if we don't have any pipes if err = s.sock.SetOption(mangos.OptionWriteQLen, 0); err != nil { s.sock.Close() return nil, err } s.rto = -1 s.sto = -1 all.AddTransports(s.sock) return &s, nil }
func (dt *devTest) Init(t *testing.T, addr string) bool { var err error if dt.Sock, err = pair.NewSocket(); err != nil { t.Fatalf("pair.NewSocket(): %v", err) } return dt.T.Init(t, addr) }
func (pt *pairTest) Init(t *testing.T, addr string) bool { var err error if pt.Sock, err = pair.NewSocket(); err != nil { pt.Errorf("NewSocket failed: %v", err) return false } return pt.T.Init(t, addr) }
// ThroughputServer is the server side -- very much equivalent to local_thr in // nanomsg/perf. It does the measurement by counting packets received. func ThroughputServer(addr string, msgSize int, count int) { s, err := pair.NewSocket() if err != nil { log.Fatalf("Failed to make new pair socket: %v", err) } defer s.Close() all.AddTransports(s) l, err := s.NewListener(addr, nil) if err != nil { log.Fatalf("Failed to make new listener: %v", err) } // Disable TCP no delay, please! - only valid for TCP l.SetOption(mangos.OptionNoDelay, false) // Make sure we linger a bit on close... err = s.SetOption(mangos.OptionLinger, time.Second) if err != nil { log.Fatalf("Failed set Linger: %v", err) } err = l.Listen() if err != nil { log.Fatalf("Failed to listen: %v", err) } msg, err := s.RecvMsg() msg.Free() start := time.Now() for i := 0; i != count; i++ { msg, err := s.RecvMsg() if err != nil { log.Fatalf("Failed to recv: %v", err) } if len(msg.Body) != msgSize { log.Fatalf("Received wrong message size: %d != %d", len(msg.Body), msgSize) } // return to cache to avoid GC msg.Free() } finish := time.Now() delta := finish.Sub(start) deltasec := float64(delta) / float64(time.Second) msgpersec := float64(count) / deltasec mbps := (float64((count)*8*msgSize) / deltasec) / 1000000.0 fmt.Printf("message size: %d [B]\n", msgSize) fmt.Printf("message count: %d\n", count) fmt.Printf("throughput: %d [msg/s]\n", uint64(msgpersec)) fmt.Printf("throughput: %.3f [Mb/s]\n", mbps) }
func testDevChain(t *testing.T, addr1 string, addr2 string, addr3 string) { // This tests using multiple devices across a few transports. // It looks like this: addr1->addr2->addr3 <==> addr3->addr2->addr1 var err error s := make([]mangos.Socket, 5) for i := 0; i < 5; i++ { if s[i], err = pair.NewSocket(); err != nil { t.Errorf("Failed to open S1_1: %v", err) return } defer s[i].Close() s[i].AddTransport(tcp.NewTransport()) s[i].AddTransport(inproc.NewTransport()) s[i].AddTransport(tlstcp.NewTransport()) s[i].AddTransport(ipc.NewTransport()) s[i].AddTransport(ws.NewTransport()) } if err = s[0].Listen(addr1); err != nil { t.Errorf("s[0] Listen: %v", err) return } if err = s[1].Dial(addr2); err != nil { t.Errorf("s[1] Dial: %v", err) return } if err = s[2].Listen(addr2); err != nil { t.Errorf("s[2] Listen: %v", err) return } if err = s[3].Dial(addr3); err != nil { t.Errorf("s[3] Dial: %v", err) return } if err = s[4].Listen(addr3); err != nil { t.Errorf("s[4] Listen: %v", err) return } if err = mangos.Device(s[0], s[1]); err != nil { t.Errorf("s[0],s[1] Device: %v", err) return } if err = mangos.Device(s[2], s[3]); err != nil { t.Errorf("s[2],s[3] Device: %v", err) return } if err = mangos.Device(s[4], nil); err != nil { t.Errorf("s[4] Device: %v", err) return } RunTests(t, addr1, deviceCaseClient()) }
func node0(url string) { var sock mangos.Socket var err error if sock, err = pair.NewSocket(); err != nil { die("can't get new pair socket: %s", err) } sock.AddTransport(ipc.NewTransport()) sock.AddTransport(tcp.NewTransport()) if err = sock.Listen(url); err != nil { die("can't listen on pair socket: %s", err.Error()) } sendRecv(sock, "node0") }
// LatencyClient is the client side of the latency test. It measures round // trip times, and is the equivalent to nanomsg/perf/remote_lat. func LatencyClient(addr string, msgSize int, roundTrips int) { s, err := pair.NewSocket() if err != nil { log.Fatalf("Failed to make new pair socket: %v", err) } defer s.Close() all.AddTransports(s) d, err := s.NewDialer(addr, nil) if err != nil { log.Fatalf("Failed to make new dialer: %v", err) } // TCP no delay, please! d.SetOption(mangos.OptionNoDelay, true) // Make sure we linger a bit on close... err = s.SetOption(mangos.OptionLinger, time.Second) if err != nil { log.Fatalf("Failed set Linger: %v", err) } err = d.Dial() if err != nil { log.Fatalf("Failed to dial: %v", err) } // 100 milliseconds to give TCP a chance to establish //time.Sleep(time.Millisecond * 100) msg := mangos.NewMessage(msgSize) msg.Body = msg.Body[0:msgSize] start := time.Now() for i := 0; i < roundTrips; i++ { if err = s.SendMsg(msg); err != nil { log.Fatalf("Failed SendMsg: %v", err) } if msg, err = s.RecvMsg(); err != nil { log.Fatalf("Failed RecvMsg: %v", err) } } finish := time.Now() msg.Free() total := (finish.Sub(start)) / time.Microsecond lat := float64(total) / float64(roundTrips*2) fmt.Printf("message size: %d [B]\n", msgSize) fmt.Printf("round trip count: %d\n", roundTrips) fmt.Printf("average latency: %.3f [us]\n", lat) }
func TestDeviceFirstNil(t *testing.T) { s1, err := pair.NewSocket() if err != nil { t.Errorf("Failed to open S1: %v", err) return } defer s1.Close() switch err := mangos.Device(nil, s1); err { case nil: t.Logf("Ok!") return default: t.Errorf("Got unexpected err: %v", err) return } }
// ThroughputClient is the client side of the latency test. It simply sends // the requested number of packets of given size to the server. It corresponds // to remote_thr. func ThroughputClient(addr string, msgSize int, count int) { s, err := pair.NewSocket() if err != nil { log.Fatalf("Failed to make new pair socket: %v", err) } defer s.Close() all.AddTransports(s) d, err := s.NewDialer(addr, nil) if err != nil { log.Fatalf("Failed to make new dialer: %v", err) } // Disable TCP no delay, please! d.SetOption(mangos.OptionNoDelay, false) // Make sure we linger a bit on close... err = s.SetOption(mangos.OptionLinger, time.Second) if err != nil { log.Fatalf("Failed set Linger: %v", err) } err = d.Dial() if err != nil { log.Fatalf("Failed to dial: %v", err) } // 100 milliseconds to give TCP a chance to establish time.Sleep(time.Millisecond * 100) body := make([]byte, msgSize) for i := 0; i < msgSize; i++ { body[i] = 111 } // send the start message s.Send([]byte{}) for i := 0; i < count; i++ { if err = s.Send(body); err != nil { log.Fatalf("Failed SendMsg: %v", err) } } }
// LatencyServer is the server side -- very much equivalent to local_lat in // nanomsg/perf. It does no measurement at all, just sends packets on the wire. func LatencyServer(addr string, msgSize int, roundTrips int) { s, err := pair.NewSocket() if err != nil { log.Fatalf("Failed to make new pair socket: %v", err) } defer s.Close() all.AddTransports(s) l, err := s.NewListener(addr, nil) if err != nil { log.Fatalf("Failed to make new listener: %v", err) } // TCP no delay, please! l.SetOption(mangos.OptionNoDelay, true) // Make sure we linger a bit on close... err = s.SetOption(mangos.OptionLinger, time.Second) if err != nil { log.Fatalf("Failed set Linger: %v", err) } err = l.Listen() if err != nil { log.Fatalf("Failed to listen: %v", err) } for i := 0; i != roundTrips; i++ { msg, err := s.RecvMsg() if err != nil { log.Fatalf("Failed to recv: %v", err) } if len(msg.Body) != msgSize { log.Fatalf("Received wrong message size: %d != %d", len(msg.Body), msgSize) } if err = s.SendMsg(msg); err != nil { log.Fatalf("Failed to send: %v", err) } } }
func benchmarkPair(t *testing.B, url string, size int) { if strings.HasPrefix(url, "ipc://") && runtime.GOOS == "windows" { t.Skip("IPC not supported on Windows") return } srvopts := make(map[string]interface{}) cliopts := make(map[string]interface{}) if strings.HasPrefix(url, "wss://") || strings.HasPrefix(url, "tls+tcp://") { srvopts[mangos.OptionTLSConfig] = srvCfg cliopts[mangos.OptionTLSConfig] = cliCfg } finish := make(chan struct{}) ready := make(chan struct{}) srvsock, err := pair.NewSocket() if err != nil || srvsock == nil { t.Errorf("Failed creating server socket: %v", err) return } all.AddTransports(srvsock) defer srvsock.Close() clisock, err := pair.NewSocket() if err != nil || clisock == nil { t.Errorf("Failed creating client socket: %v", err) return } all.AddTransports(clisock) defer clisock.Close() go func() { var err error var m *mangos.Message if err = srvsock.ListenOptions(url, srvopts); err != nil { t.Errorf("Server listen failed: %v", err) return } close(ready) for i := 0; i < t.N; i++ { if m, err = srvsock.RecvMsg(); err != nil { t.Errorf("Error receiving %d: %v", i, err) return } m.Free() } close(finish) }() <-ready if err = clisock.DialOptions(url, cliopts); err != nil { t.Errorf("Client dial failed: %v", err) return } time.Sleep(700 * time.Millisecond) t.ResetTimer() for i := 0; i < t.N; i++ { msg := mangos.NewMessage(size) if err = clisock.SendMsg(msg); err != nil { t.Errorf("Client send failed: %v", err) return } } <-finish t.StopTimer() if size > 128 { t.SetBytes(int64(size)) } }