// Connect to addr and send/receive a message. func client(addr net.Addr) { if c, err := electron.Dial(addr.Network(), addr.String()); check("dial", err) { defer c.Close(nil) if s, err := c.Sender(electron.Target("target")); check("sender", err) { fmt.Printf("client sending\n") s.SendSync(amqp.NewMessageWith("hello")) // Send and wait for server to Accept() } if r, err := c.Receiver(electron.Source("source")); check("receiver", err) { if rm, err := r.Receive(); err == nil { fmt.Printf("client received %q\n", rm.Message.Body()) } } } }
func TestClientReceiver(t *testing.T) { nMessages := 3 client, server := newClientServer(t) go func() { for in := range server.Incoming() { switch in := in.(type) { case *IncomingSender: s := in.Accept().(Sender) go func() { for i := int32(0); i < int32(nMessages); i++ { out := s.SendSync(amqp.NewMessageWith(i)) if out.Error != nil { t.Error(out.Error) return } } s.Close(nil) }() default: in.Accept() } } }() r, err := client.Receiver(Source("foo")) if err != nil { t.Fatal(err) } for i := int32(0); i < int32(nMessages); i++ { rm, err := r.Receive() if err != nil { if err != Closed { t.Error(err) } break } if err := rm.Accept(); err != nil { t.Error(err) } if b, ok := rm.Message.Body().(int32); !ok || b != i { t.Errorf("want %v, true got %v, %v", i, b, ok) } } server.Close(nil) client.Connection().Close(nil) }
func TestClientReceiver(t *testing.T) { nMessages := 3 client, server := newClientServer(t, func(i Incoming) { switch i := i.(type) { case *IncomingSender: s := i.AcceptSender() go func() { for i := int32(0); i < int32(nMessages); i++ { sm, err := s.Send(amqp.NewMessageWith(i)) if err != nil { t.Error(err) return } else { sm.Disposition() // Sync send. } } s.Close(nil) }() default: i.Accept() } }) r, err := client.Receiver(Source("foo")) if err != nil { t.Fatal(err) } for i := int32(0); i < int32(nMessages); i++ { rm, err := r.Receive() if err != nil { if err != Closed { t.Error(err) } break } if err := rm.Accept(); err != nil { t.Error(err) } if b, ok := rm.Message.Body().(int32); !ok || b != i { t.Errorf("want %v, true got %v, %v", i, b, ok) } } server.Close(nil) client.Connection().Close(nil) }
func runServer(cont electron.Container, l net.Listener) { for c, err := cont.Accept(l); check("accept connection", err); c, err = cont.Accept(l) { go func() { // Process connections concurrently, accepting AMQP endpoints for in := range c.Incoming() { ep := in.Accept() // Accept all endpoints go func() { // Process endpoints concurrently switch ep := ep.(type) { case electron.Sender: m := amqp.NewMessageWith("hello yourself") fmt.Printf("server %q sending %q\n", ep.Source(), m.Body()) ep.SendForget(m) // One-way send, client does not need to Accept. case electron.Receiver: if rm, err := ep.Receive(); check("server receive", err) { fmt.Printf("server %q received %q\n", ep.Target(), rm.Message.Body()) err := rm.Accept() // Client is waiting for Accept. check("accept message", err) } } }() } }() } }
// Send a message one way with a client sender and server receiver, verify ack. func TestClientSendServerReceive(t *testing.T) { timeout := time.Second * 2 nLinks := 3 nMessages := 3 rchan := make(chan Receiver, nLinks) client, server := newClientServer(t, func(i Incoming) { switch i := i.(type) { case *IncomingReceiver: rchan <- i.AcceptReceiver(1, false) default: i.Accept() } }) defer func() { closeClientServer(client, server) }() s := make([]Sender, nLinks) for i := 0; i < nLinks; i++ { var err error s[i], err = client.Sender(Target(fmt.Sprintf("foo%d", i))) if err != nil { t.Fatal(err) } } r := make([]Receiver, nLinks) for i := 0; i < nLinks; i++ { r[i] = <-rchan } for i := 0; i < nLinks; i++ { for j := 0; j < nMessages; j++ { var sm SentMessage // Client send sendDone := make(chan struct{}) go func() { defer close(sendDone) m := amqp.NewMessageWith(fmt.Sprintf("foobar%v-%v", i, j)) var err error sm, err = s[i].Send(m) if err != nil { t.Fatal(err) } }() // Server recieve rm, err := r[i].Receive() if err != nil { t.Fatal(err) } if want, got := interface{}(fmt.Sprintf("foobar%v-%v", i, j)), rm.Message.Body(); want != got { t.Errorf("%#v != %#v", want, got) } // Should not be acknowledged on client yet <-sendDone if d, err := sm.DispositionTimeout(0); err != Timeout || NoDisposition != d { t.Errorf("want [no-disposition/timeout] got [%v/%v]", d, err) } // Server ack if err := rm.Acknowledge(Rejected); err != nil { t.Error(err) } // Client get ack. if d, err := sm.DispositionTimeout(timeout); err != nil || Rejected != d { t.Errorf("want [rejected/nil] got [%v/%v]", d, err) } } } }
// Send a message one way with a client sender and server receiver, verify ack. func TestClientSendServerReceive(t *testing.T) { nLinks := 3 nMessages := 3 rchan := make(chan Receiver, nLinks) client, server := newClientServer(t) go func() { for in := range server.Incoming() { switch in := in.(type) { case *IncomingReceiver: in.SetCapacity(1) in.SetPrefetch(false) rchan <- in.Accept().(Receiver) default: in.Accept() } } }() defer func() { closeClientServer(client, server) }() s := make([]Sender, nLinks) for i := 0; i < nLinks; i++ { var err error s[i], err = client.Sender(Target(fmt.Sprintf("foo%d", i))) if err != nil { t.Fatal(err) } } r := make([]Receiver, nLinks) for i := 0; i < nLinks; i++ { r[i] = <-rchan } for i := 0; i < nLinks; i++ { for j := 0; j < nMessages; j++ { // Client send ack := make(chan Outcome, 1) sendDone := make(chan struct{}) go func() { defer close(sendDone) m := amqp.NewMessageWith(fmt.Sprintf("foobar%v-%v", i, j)) var err error s[i].SendAsync(m, ack, "testing") if err != nil { t.Fatal(err) } }() // Server recieve rm, err := r[i].Receive() if err != nil { t.Fatal(err) } if want, got := interface{}(fmt.Sprintf("foobar%v-%v", i, j)), rm.Message.Body(); want != got { t.Errorf("%#v != %#v", want, got) } // Should not be acknowledged on client yet <-sendDone select { case <-ack: t.Errorf("unexpected ack") default: } // Server send ack if err := rm.Reject(); err != nil { t.Error(err) } // Client get ack. if a := <-ack; a.Value != "testing" || a.Error != nil || a.Status != Rejected { t.Error("unexpected ack: ", a.Status, a.Error, a.Value) } } } }