func reflector(t *testing.T, s *zmq.Socket, n int, wg *sync.WaitGroup) chan bool { s.SetRcvtimeo(time.Second) s.SetSndtimeo(time.Second) svcrouter.Barrier() wg.Add(1) c := make(chan bool) go func() { /* this is a nasty hack but is OK for a test program I guess */ for { if msg, err := s.RecvMessageBytes(0); err == nil { svcrouter.DumpMsg(fmt.Sprintf("reflector %d", n), msg) if _, err := s.SendMessage(msg); err != nil { wg.Done() t.Fatal(err) return } } select { case <-c: wg.Done() return default: } } }() return c }
func TestServiceRouter(t *testing.T) { numPeers := 50 numServices := 100 var c *zmq.Context var m *Mirror var socks []*zmq.Socket = make([]*zmq.Socket, numPeers) var addr []string = make([]string, numPeers) var err error defer func() { for _, s := range socks { if s != nil { s.Close() } } if m != nil { m.Close() } if c != nil { c.Term() } }() if c, err = zmq.NewContext(); err != nil { t.Fatalf("Failed to create ZMQ context: %v", err) } if m, err = NewMirror(t, c, 1); err != nil { t.Fatalf("Failed to create a new mirror: %v", err) } for np := 0; np < numPeers; np++ { if socks[np], addr[np], err = svcrouter.NewHalfPair(c, true); err != nil { t.Fatalf("Failed to create half pair A: %v", err) } if err = m.AddPeer(svcrouter.PeerDefinition{ Name: dummyPeerName(np), ZmqType: zmq.PAIR, Address: addr[np], Bind: false, PeerImpl: &MirrorPeerImpl{}, }); err != nil { t.Fatalf("Could not add peer %d: %v", np, err) } } svcrouter.Barrier() r := svcrouter.NewServiceRouter() t.Log("Adding by Peer/Service") for np := 0; np < numPeers; np++ { peerName := dummyPeerName(np) for ns := 0; ns < numServices; ns++ { serviceType, serviceId := dummyServiceName(ns) e := svcrouter.NewEndpointEnvelope(serviceType, serviceId, "") if err := r.AddService(m.RouterElement, peerName, e); err != nil { t.Fatalf("Could not add service %d to peer %d: %v", ns, np, err) } } } if err := r.Validate(); err != nil { t.Fatalf("Failed validation 1: %v", err) } for np := 0; np < numPeers; np++ { peerName := dummyPeerName(np) if l := r.LenPeerEntries(m.RouterElement, peerName); l != numServices { t.Fatalf("Peer %d has service element mismatch: %d != %d", l, numServices) } } t.Log("Removing by Service/Peer") for ns := 0; ns < numServices; ns++ { serviceType, serviceId := dummyServiceName(ns) for np := 0; np < numPeers; np++ { peerName := dummyPeerName(np) e := svcrouter.NewEndpointEnvelope(serviceType, serviceId, "") if err := r.DeleteService(m.RouterElement, peerName, e); err != nil { t.Fatalf("Could not delete service %d to peer %d: %v", ns, np, err) } } if ns%(numServices/10) == 0 { if err := r.Validate(); err != nil { t.Fatalf("Failed validation 2: %v", err) } } } for np := 0; np < numPeers; np++ { peerName := dummyPeerName(np) if l := r.LenPeerEntries(m.RouterElement, peerName); l != 0 { t.Fatalf("Peer %d has service element mismatch: %d != 0", l) } } if err := r.Validate(); err != nil { t.Fatalf("Failed validation 3: %v", err) } t.Log("Adding by Service/Peer") for ns := 0; ns < numServices; ns++ { serviceType, serviceId := dummyServiceName(ns) for np := 0; np < numPeers; np++ { peerName := dummyPeerName(np) e := svcrouter.NewEndpointEnvelope(serviceType, serviceId, "") if err := r.AddService(m.RouterElement, peerName, e); err != nil { t.Fatalf("Could not add service %d to peer %d: %v", ns, np, err) } } } if err := r.Validate(); err != nil { t.Fatalf("Failed validation 4: %v", err) } for np := 0; np < numPeers; np++ { peerName := dummyPeerName(np) if l := r.LenPeerEntries(m.RouterElement, peerName); l != numServices { t.Fatalf("Peer %d has service element mismatch: %d != %d", l, numServices) } } t.Log("Removing by Peer/Service") for np := 0; np < numPeers; np++ { peerName := dummyPeerName(np) for ns := 0; ns < numServices; ns++ { serviceType, serviceId := dummyServiceName(ns) e := svcrouter.NewEndpointEnvelope(serviceType, serviceId, "") if err := r.DeleteService(m.RouterElement, peerName, e); err != nil { t.Fatalf("Could not delete service %d to peer %d: %v", ns, np, err) } } if np%10 == 0 { if err := r.Validate(); err != nil { t.Fatalf("Failed validation 5: %v", err) } } } if err := r.Validate(); err != nil { t.Fatalf("Failed validation 6: %v", err) } for np := 0; np < numPeers; np++ { peerName := dummyPeerName(np) if l := r.LenPeerEntries(m.RouterElement, peerName); l != 0 { t.Fatalf("Peer %d has service element mismatch: %d != 0", l) } } t.Log("Adding by Service/Peer") for ns := 0; ns < numServices; ns++ { serviceType, serviceId := dummyServiceName(ns) for np := 0; np < numPeers; np++ { peerName := dummyPeerName(np) e := svcrouter.NewEndpointEnvelope(serviceType, serviceId, "") if err := r.AddService(m.RouterElement, peerName, e); err != nil { t.Fatalf("Could not add service %d to peer %d: %v", ns, np, err) } } } if err := r.Validate(); err != nil { t.Fatalf("Failed validation 7: %v", err) } for it := 0; it < 10; it++ { // How exciting. Let's try some routing! serviceType, serviceId := dummyServiceName(0) d := make(map[string]int, numPeers) for np := 0; np < numPeers; np++ { se := r.GetServerEntry(serviceType, serviceId, "") d[se.Peer.Name] += 1 } if len(d) != numPeers { t.Fatalf("Failed load balance test 1") } for np := 0; np < numPeers; np++ { se := r.GetServerEntry(serviceType, serviceId, "") if d[se.Peer.Name] != 1 { t.Fatalf("Failed load balance test 2") } d[se.Peer.Name] += 1 } if len(d) != numPeers { t.Fatalf("Failed load balance test 3") } } for np := 0; np < numPeers; np++ { peerName := dummyPeerName(np) if l := r.LenPeerEntries(m.RouterElement, peerName); l != numServices { t.Fatalf("Peer %d has service element mismatch: %d != %d", l, numServices) } } t.Log("Removing by Peer (all entries)") for np := 0; np < numPeers; np++ { peerName := dummyPeerName(np) if err := r.DeleteAllPeerEntries(m.RouterElement, peerName); err != nil { t.Fatalf("Could not add delete all services from peer %d: %v", np, err) } } for np := 0; np < numPeers; np++ { peerName := dummyPeerName(np) if l := r.LenPeerEntries(m.RouterElement, peerName); l != 0 { t.Fatalf("Peer %d has service element mismatch: %d != 0", l) } } if err := r.Validate(); err != nil { t.Fatalf("Failed validation final: %v", err) } }
func TestRouterElement(t *testing.T) { var c *zmq.Context var m *Mirror var sa, sb *zmq.Socket var err error var addra string var addrb string defer func() { if sa != nil { sa.Close() } if sb != nil { sb.Close() } if m != nil { m.Close() } if c != nil { c.Term() } }() if c, err = zmq.NewContext(); err != nil { t.Fatalf("Failed to create ZMQ context: %v", err) } if m, err = NewMirror(t, c, 1); err != nil { t.Fatalf("Failed to create a new mirror: %v", err) } if sa, addra, err = svcrouter.NewHalfPair(c, true); err != nil { t.Fatalf("Failed to create half pair A: %v", err) } if sb, addrb, err = svcrouter.NewHalfPair(c, true); err != nil { t.Fatalf("Failed to create half pair B: %v", err) } if err = m.AddPeer(svcrouter.PeerDefinition{ Name: "ab", ZmqType: zmq.PAIR, Address: addra, Bind: false, PeerImpl: &MirrorPeerImpl{}, }); err != nil { t.Fatalf("Could not add peer A: %v", err) } if err = m.AddPeer(svcrouter.PeerDefinition{ Name: "ba", ZmqType: zmq.PAIR, Address: addrb, Bind: false, PeerImpl: &MirrorPeerImpl{}, }); err != nil { t.Fatalf("Could not add peer B: %v", err) } svcrouter.Barrier() num := 100 var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() for i := 0; i < num; i++ { if _, err := sb.RecvMessage(0); err != nil { t.Fatalf("sb receive error: %v", err) } } }() msg := [][]byte{[]byte("Hello"), []byte("World")} for i := 0; i < num; i++ { if _, err := sa.SendMessage(msg); err != nil { t.Fatalf("sa send error: %v", err) } } wg.Wait() }
func TestServiceDispatcher(t *testing.T) { numPeers := 10 numServices := 10 var c *zmq.Context var sd *svcrouter.ServiceDispatcher var socks []*zmq.Socket = make([]*zmq.Socket, numPeers) var addr []string = make([]string, numPeers) var killReflectors []chan bool = make([]chan bool, numPeers) var err error var wg sync.WaitGroup defer func() { for _, s := range socks { if s != nil { s.Close() } } if sd != nil { sd.Close() } if c != nil { c.Term() } }() if c, err = zmq.NewContext(); err != nil { t.Fatalf("Failed to create ZMQ context: %v", err) } if sd, err = svcrouter.NewServiceDispatcher(c, 1); err != nil { t.Fatalf("Failed to create a new service dispatcher: %v", err) } sd.NoEnvRouterPeer = dummyPeerName(0) sd.EnvRouterPeer = dummyPeerName(2) for np := 0; np < numPeers; np++ { if np%2 == 0 { name := fmt.Sprintf("C%04d st=ST%d si=x", np, (np/2)%2) if socks[np], addr[np], err = svcrouter.NewSocketAndAddress(c, true, zmq.REQ, name); err != nil { t.Fatalf("Failed to create half pair A: %v", err) } if err = sd.AddPeer(svcrouter.PeerDefinition{ Name: dummyPeerName(np), ZmqType: zmq.ROUTER, Address: addr[np], Bind: false, }, svcrouter.PT_CLIENTSNOENV); err != nil { t.Fatalf("Could not add peer %d: %v", np, err) } } else { name := fmt.Sprintf("C%04d st=ST%d si=x", np, ((np-1)/2)%2) if socks[np], addr[np], err = svcrouter.NewSocketAndAddress(c, true, zmq.REP, name); err != nil { t.Fatalf("Failed to create half pair A: %v", err) } if err = sd.AddPeer(svcrouter.PeerDefinition{ Name: dummyPeerName(np), ZmqType: zmq.DEALER, Address: addr[np], Bind: false, }, svcrouter.PT_DOWNSTREAMENVREP); err != nil { t.Fatalf("Could not add peer %d: %v", np, err) } killReflectors[np] = reflector(t, socks[np], np, &wg) } } svcrouter.Barrier() for np := 1; np < numPeers; np += 2 { for ns := 0; ns < numServices; ns++ { serviceType := fmt.Sprintf("ST%d", ns) serviceId := "x" e := svcrouter.NewEndpointEnvelope(serviceType, serviceId, "") if err := sd.AddService(sd.RouterElement, dummyPeerName(np), e); err != nil { t.Fatalf("Could not add service %d to peer %d: %v", ns, np, err) } } } msg := [][]byte{[]byte("Hello"), []byte("World")} for it := 0; it < 2; it++ { if _, err := socks[0].SendMessage(msg); err != nil { t.Fatalf("socks send error: %v", err) } if msg2, err := socks[0].RecvMessageBytes(0); err != nil { t.Fatalf("socks receive error: %v", err) } else { svcrouter.DumpMsg("FINAL", msg2) if !msgEqual(msg, msg2) { t.Fatalf("socks messages differ") } } } for _, v := range killReflectors { if v != nil { close(v) } } wg.Wait() }