func TestSubscribe(t *testing.T) { h, err := newTestHub() assert.NoError(t, err) defer h.Close() assert.True(t, h.IsRunning(time.Millisecond)) conn := NewMockConnection() /* register the connection and validate registered */ err = h.Register(conn) assert.NoError(t, err) topic := &TestTopic{} /* Count the number of subscriptions */ assert.EqualValues(t, 0, h.SubscriptionTopicCount()) i, err := h.TopicConnectionCount(topic) assert.Error(t, err) assert.EqualValues(t, 0, i) /* add a subscription*/ err = h.Subscribe(conn, topic, interfacehub.NewFilters(topic)) assert.NoError(t, err) /* Count the number of subscriptions */ assert.EqualValues(t, 1, h.SubscriptionTopicCount()) i, err = h.TopicConnectionCount(topic) assert.NoError(t, err) assert.EqualValues(t, 1, i) /* re-add the subscription should fail and counts remain same*/ err = h.Subscribe(conn, topic, interfacehub.NewFilters(topic)) assert.Error(t, err) assert.EqualValues(t, 1, h.SubscriptionTopicCount()) i, err = h.TopicConnectionCount(topic) assert.NoError(t, err) assert.EqualValues(t, 1, i) /* subscribe conn nil */ err = h.Subscribe(nil, topic, interfacehub.NewFilters(topic)) assert.Error(t, err) /* subscribe topic nil */ err = h.Subscribe(conn, nil, interfacehub.NewFilters(nil)) assert.Error(t, err) /* subscribe filters nil */ topic2 := &TestTopic2{} err = h.Subscribe(conn, topic2, nil) assert.NoError(t, err) /* subscribe on closed */ err = h.Close() assert.NoError(t, err) err = h.Subscribe(conn, topic, interfacehub.NewFilters(topic)) assert.Error(t, err) }
func TestNewFilters(t *testing.T) { topic := &TestTopic{} f := interfacehub.NewFilters(topic) assert.IsType(t, &interfacehub.Filters{}, f) assert.Equal(t, topic, f.Topic()) }
func TestTopicConnectionCount(t *testing.T) { h, err := newTestHub() assert.NoError(t, err) defer h.Close() assert.True(t, h.IsRunning(time.Millisecond)) conn := NewMockConnection() /* register the connection and validate registered */ err = h.Register(conn) assert.NoError(t, err) /* Count the number of subscriptions */ assert.EqualValues(t, 0, h.SubscriptionTopicCount()) i, err := h.TopicConnectionCount(TestTopic{}) assert.Error(t, err) assert.EqualValues(t, 0, i) /* add a subscription*/ topic := &TestTopic{} err = h.Subscribe(conn, topic, interfacehub.NewFilters(topic)) assert.NoError(t, err) /* Re-count the number of subscriptions */ assert.EqualValues(t, 1, h.SubscriptionTopicCount()) i, err = h.TopicConnectionCount(topic) assert.NoError(t, err) assert.EqualValues(t, 1, i) /* count nil topic */ i, err = h.TopicConnectionCount(nil) assert.Error(t, err) assert.EqualValues(t, 0, i) }
func TestPublish(t *testing.T) { h, err := newTestHub() assert.NoError(t, err) defer h.Close() assert.True(t, h.IsRunning(time.Millisecond)) conn := NewMockConnection() conn2 := NewMockConnection() /* register the connection and validate registered */ err = h.Register(conn) assert.NoError(t, err) err = h.Register(conn2) assert.NoError(t, err) /* add a subscription*/ topic := &TestPublishOutput{} err = h.Subscribe(conn, topic, interfacehub.NewFilters(topic)) assert.NoError(t, err) err = h.Subscribe(conn2, topic, interfacehub.NewFilters(topic)) assert.NoError(t, err) pubmsg := make(chan interface{}, 1) conn.SetSendDest(pubmsg) /* Publish something to and ensure conn don't see it*/ msg := uniqueString() err = h.Publish(conn, &TestPublishOutput{msg: msg}) assert.NoError(t, err) var i interface{} select { case i = <-pubmsg: case <-time.After(time.Millisecond): } assert.Nil(t, i) /* Publish something to and ensure conn does see it*/ msg = uniqueString() err = h.Publish(conn2, &TestPublishOutput{msg: msg}) assert.NoError(t, err) select { case i = <-pubmsg: case <-time.After(time.Millisecond): } assert.NotNil(t, i) if i != nil { p := i.(*TestPublishOutput) assert.EqualValues(t, p.msg, msg) } /* Publish something to delayed connections */ conn.SetDelay(10 * time.Millisecond) err = h.Publish(conn2, &TestPublishOutput{msg: uniqueString()}) assert.NoError(t, err) /* This should take too long and error */ err = h.Publish(conn2, &TestPublishOutput{msg: uniqueString()}) assert.Error(t, err) conn.SetDelay(time.Duration(0)) /* conn should be unregistered */ b, err := h.IsRegistered(conn) assert.NoError(t, err) assert.False(t, b) /* Publish to deregistered connection */ err = h.Publish(conn, &TestPublishOutput{msg: uniqueString()}) assert.Error(t, err) /* re-register the connection and validate registered */ conn = NewMockConnection() err = h.Register(conn) assert.NoError(t, err) /* Publish nil */ err = h.Publish(conn, nil) assert.Error(t, err) /* Publish nil conn*/ err = h.Publish(nil, &TestPublishOutput{msg: "Nothing!"}) assert.Error(t, err) /* Publish to closed */ err = h.Close() assert.NoError(t, err) err = h.Publish(conn, &TestPublishOutput{msg: "Hi Testy More!"}) assert.Error(t, err) }
func Example() { /* create a hub */ hub, err := interfacehub.NewHub() if err != nil { log.Fatalf("Unable to create new hub: %s\n", err) } defer hub.Close() /* Done channel to shut stuff down*/ Done := make(chan bool) /* create a client subscribe channel */ cc := connector.NewIntegratedConnection("interfacehub example client", "Client Conn") cc.SetHub(hub) err = cc.Register() if err != nil { log.Fatalf("Unable to regoster client connection: %s\n", err) } /* Set up the filters for the client to listen on */ csf := interfacehub.NewFilters(&ExampleServerOutput{}) csf.Add(&filter.Equal{ Description: "Filter to accept specific messages", Field: "Rejected", ActionOnMatch: filter.FILTER_ACTION_DENY, ActionOnNoMatch: filter.FILTER_ACTION_CONTINUE, ExpectedValue: true, }) csf.Add(&filter.Equal{ Description: "Filter to reject empty messages and accept everything else", Field: "UpperCaseMessage", ActionOnMatch: filter.FILTER_ACTION_DENY, ActionOnNoMatch: filter.FILTER_ACTION_ACCEPT, ExpectedValue: "", }) /* set up a client to print the server output received */ clientmsg := make(chan interface{}, 1) cc.SetSendDestination(clientmsg) /* have the client print out what it receives */ var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() for { select { case <-Done: return case i := <-clientmsg: v, ok := i.(*ExampleServerOutput) if !ok { log.Fatal("Expected ExampleServerOutput message") } fmt.Printf("Echo from server: %s\n", v.UpperCaseMessage) } } }() /* do our client subscription to listen for the server response */ err = cc.Subscribe(&ExampleServerOutput{}, csf) if err != nil { log.Fatalf("Could not subscribe client: %s\n", err) } /* create a server subscribe channel */ sc := connector.NewIntegratedConnection("interfacehub example server", "Server Conn") sc.SetHub(hub) sc.Register() /* set up a server channel to listen */ servermsg := make(chan interface{}, 1) sc.SetSendDestination(servermsg) /* have the server reflect back in upper case */ wg.Add(1) go func(conn *connector.IntegratedConnection) { defer wg.Done() for { select { case <-Done: return case i := <-servermsg: v, ok := i.(*ExampleServerInput) if !ok { log.Fatal("Expected ServerOutput message") return } conn.Publish(&ExampleServerOutput{ Rejected: v.Reject, UpperCaseMessage: strings.ToUpper(v.Message), }) } } }(sc) /* do our server subscription to listen for the client requests */ err = sc.Subscribe(&ExampleServerInput{}, nil) if err != nil { log.Fatalf("Could not subscribe server: %s\n", err) } /* Send the message*s from the client connection */ msg := "My client message" fmt.Printf("Client Sending to server: %s\n", msg) err = cc.Publish(&ExampleServerInput{ Message: msg, Reject: false, }) if err != nil { log.Fatalf("Could not publish to server: %s\n", err) } time.Sleep(1 * time.Millisecond) msg = "Another to be rejected by filter client message" fmt.Printf("Client Sending to server: %s\n", msg) err = cc.Publish(&ExampleServerInput{ Message: msg, Reject: true, }) if err != nil { log.Fatalf("Could not publish to server: %s\n", err) } time.Sleep(1 * time.Millisecond) msg = "Last client message" fmt.Printf("Client Sending to server: %s\n", msg) err = cc.Publish(&ExampleServerInput{ Message: msg, Reject: false, }) if err != nil { log.Fatalf("Could not publish to server: %s\n", err) } time.Sleep(1 * time.Millisecond) Done <- true Done <- true wg.Wait() // Output: // Client Sending to server: My client message // Echo from server: MY CLIENT MESSAGE // Client Sending to server: Another to be rejected by filter client message // Client Sending to server: Last client message // Echo from server: LAST CLIENT MESSAGE }
func TestClientServerEcho(t *testing.T) { /* create a hub */ hub, _ := interfacehub.NewHub() defer hub.Close() /* create a client subscribe channel */ cc := connector.NewIntegratedConnection("interfacehub Unit Tests", "Client Conn") cc.SetHub(hub) cc.Register() /* create a server subscribe channel */ sc := connector.NewIntegratedConnection("interfacehub Unit Tests", "Server Conn") sc.SetHub(hub) sc.Register() /* set up a client to print the server output received */ pubmsg := make(chan interface{}, 1) cc.SetSendDestination(pubmsg) /* Set up the filters for the client to listen on */ csf := interfacehub.NewFilters(&ServerOutput{}) csf.Add(&filter.Equal{ Description: "Filter to accept specific messages", // Rule description Field: "UpperCaseMessage", // Interface field to match on ActionOnMatch: filter.FILTER_ACTION_ACCEPT, // Action on match ActionOnNoMatch: filter.FILTER_ACTION_CONTINUE, // Action on not match ExpectedValue: "MESSAGE WE ALWAYS WANT EVEN REJECTED", // Value interface field must match }) csf.Add(&filter.Equal{ Description: "Filter to reject tagged messages", Field: "Rejected", ActionOnMatch: filter.FILTER_ACTION_ACCEPT, ActionOnNoMatch: filter.FILTER_ACTION_CONTINUE, ExpectedValue: false, }) csf.Add(&filter.Equal{ Description: "Everything we want to reject", Field: "UpperCaseMessage", ActionOnMatch: filter.FILTER_ACTION_DENY, ActionOnNoMatch: filter.FILTER_ACTION_DENY, ExpectedValue: "", }) /* do our client subscription to listen for the server response*/ err := cc.Subscribe(&ServerOutput{}, csf) assert.NoError(t, err) err = sc.Publish(&ServerOutput{ UpperCaseMessage: "MESSAGE WE ALWAYS WANT EVEN REJECTED", Rejected: true, }) assert.NoError(t, err) var i interface{} select { case i = <-pubmsg: v, ok := i.(*ServerOutput) assert.True(t, ok) assert.Equal(t, "MESSAGE WE ALWAYS WANT EVEN REJECTED", v.UpperCaseMessage) assert.True(t, v.Rejected) case <-time.After(10 * time.Millisecond): assert.Fail(t, "Timeout waiting for ServerOutput message") } err = sc.Publish(&ServerOutput{ UpperCaseMessage: "ANOTHER MESSAGE WE WANT IF NOT REJECTED", Rejected: true, }) assert.NoError(t, err) select { case i = <-pubmsg: v, ok := i.(*ServerOutput) assert.True(t, ok) assert.Equal(t, "Nothing", v.UpperCaseMessage) case <-time.After(10 * time.Millisecond): } err = sc.Publish(&ServerOutput{ UpperCaseMessage: "ANOTHER MESSAGE WE WANT IF NOT REJECTED", Rejected: false, }) assert.NoError(t, err) select { case i = <-pubmsg: v, ok := i.(*ServerOutput) assert.True(t, ok) assert.Equal(t, "ANOTHER MESSAGE WE WANT IF NOT REJECTED", v.UpperCaseMessage) assert.False(t, v.Rejected) case <-time.After(10 * time.Millisecond): assert.Fail(t, "Timeout waiting for ServerOutput message") } }
func TestUnsubscribeConnection(t *testing.T) { h, err := newTestHub() assert.NoError(t, err) defer h.Close() assert.True(t, h.IsRunning(time.Millisecond)) conn := NewMockConnection() conn2 := NewMockConnection() conn3 := NewMockConnection() /* register the connection and validate registered */ err = h.Register(conn) assert.NoError(t, err) err = h.Register(conn2) assert.NoError(t, err) /* add a subscription*/ topic := &TestTopic{} err = h.Subscribe(conn, topic, interfacehub.NewFilters(topic)) assert.NoError(t, err) /* add another subscription for same connection different topic*/ topic3 := &TestTopic2{} err = h.Subscribe(conn, topic3, interfacehub.NewFilters(topic3)) assert.NoError(t, err) /* add another subscription for different connection same topic */ err = h.Subscribe(conn2, topic, interfacehub.NewFilters(topic)) assert.NoError(t, err) /* add another subscription for different connection different topic */ topic4 := &map[string]string{"key": "value"} err = h.Subscribe(conn2, topic4, interfacehub.NewFilters(topic4)) assert.NoError(t, err) /* make sure subscriptions look like we expect */ assert.EqualValues(t, 3, h.SubscriptionTopicCount()) i, err := h.TopicConnectionCount(topic) assert.NoError(t, err) assert.EqualValues(t, 2, i) i, err = h.TopicConnectionCount(topic3) assert.NoError(t, err) assert.EqualValues(t, 1, i) i, err = h.TopicConnectionCount(topic4) assert.NoError(t, err) assert.EqualValues(t, 1, i) /* we have 2 subscriptions for conn and 2 subscriptions for conn2 - with overlap in topic */ /* unsubscribe the whole connection conn */ err = h.UnsubscribeConnection(conn) assert.NoError(t, err) /* recount */ assert.EqualValues(t, 2, h.SubscriptionTopicCount()) i, err = h.TopicConnectionCount(topic) assert.NoError(t, err) assert.EqualValues(t, 1, i) i, err = h.TopicConnectionCount(topic3) assert.Error(t, err) assert.EqualValues(t, 0, i) i, err = h.TopicConnectionCount(topic4) assert.NoError(t, err) assert.EqualValues(t, 1, i) /* removal of non existent connection */ err = h.UnsubscribeConnection(conn3) assert.Error(t, err) /* unsubscribe conn nil */ err = h.UnsubscribeConnection(nil) assert.Error(t, err) assert.EqualValues(t, 2, h.SubscriptionTopicCount()) /* unsubscribe on closed */ err = h.Close() assert.NoError(t, err) err = h.UnsubscribeConnection(conn) assert.Error(t, err) assert.EqualValues(t, 0, h.SubscriptionTopicCount()) }
func TestUnsubscribe(t *testing.T) { h, err := newTestHub() assert.NoError(t, err) defer h.Close() assert.True(t, h.IsRunning(time.Millisecond)) conn := NewMockConnection() conn2 := NewMockConnection() /* register the connection and validate registered */ err = h.Register(conn) assert.NoError(t, err) err = h.Register(conn2) assert.NoError(t, err) /* Count the number of subscriptions */ assert.EqualValues(t, 0, h.SubscriptionTopicCount()) i, err := h.TopicConnectionCount(TestTopic{}) assert.Error(t, err) assert.EqualValues(t, 0, i) /* add a subscription*/ topic := &TestTopic{} err = h.Subscribe(conn, topic, interfacehub.NewFilters(topic)) assert.NoError(t, err) /* Re-count the number of subscriptions */ assert.EqualValues(t, 1, h.SubscriptionTopicCount()) i, err = h.TopicConnectionCount(topic) assert.NoError(t, err) assert.EqualValues(t, 1, i) /* add another subscription for same connection same topic*/ topic2 := &TestTopic{} err = h.Subscribe(conn, topic2, interfacehub.NewFilters(topic2)) assert.Error(t, err) assert.EqualValues(t, 1, h.SubscriptionTopicCount()) i, err = h.TopicConnectionCount(topic) assert.NoError(t, err) assert.EqualValues(t, 1, i) i, err = h.TopicConnectionCount(topic2) assert.NoError(t, err) assert.EqualValues(t, 1, i) /* add another subscription for same connection different topic*/ topic3 := &TestTopic2{} err = h.Subscribe(conn, topic3, interfacehub.NewFilters(topic3)) assert.NoError(t, err) assert.EqualValues(t, 2, h.SubscriptionTopicCount()) i, err = h.TopicConnectionCount(topic) assert.NoError(t, err) assert.EqualValues(t, 1, i) i, err = h.TopicConnectionCount(topic3) assert.NoError(t, err) assert.EqualValues(t, 1, i) /* add another subscription for different connection same topic */ err = h.Subscribe(conn2, topic, interfacehub.NewFilters(topic)) assert.NoError(t, err) assert.EqualValues(t, 2, h.SubscriptionTopicCount()) i, err = h.TopicConnectionCount(topic) assert.NoError(t, err) assert.EqualValues(t, 2, i) /* add another subscription for different connection different topic */ topic4 := &map[string]string{"key": "value"} err = h.Subscribe(conn2, topic4, interfacehub.NewFilters(topic4)) assert.NoError(t, err) assert.EqualValues(t, 3, h.SubscriptionTopicCount()) i, err = h.TopicConnectionCount(topic) assert.NoError(t, err) assert.EqualValues(t, 2, i) /* add another subscription with mismatched subscription topic and filters topic */ /* add another subscription for different connection different topic */ err = h.Subscribe(conn2, topic4, interfacehub.NewFilters(topic)) assert.Error(t, err) assert.EqualValues(t, 3, h.SubscriptionTopicCount()) i, err = h.TopicConnectionCount(topic) assert.NoError(t, err) assert.EqualValues(t, 2, i) /* remove the topic subscription*/ err = h.Unsubscribe(conn, topic) assert.NoError(t, err) assert.EqualValues(t, 3, h.SubscriptionTopicCount()) i, err = h.TopicConnectionCount(topic) assert.NoError(t, err) assert.EqualValues(t, 1, i) err = h.Unsubscribe(conn2, topic) assert.NoError(t, err) assert.EqualValues(t, 2, h.SubscriptionTopicCount()) i, err = h.TopicConnectionCount(topic) assert.Error(t, err) assert.EqualValues(t, 0, i) /* removal of non existent subscription */ err = h.Unsubscribe(conn2, topic) assert.Error(t, err) assert.EqualValues(t, 2, h.SubscriptionTopicCount()) i, err = h.TopicConnectionCount(topic) assert.Error(t, err) assert.EqualValues(t, 0, i) /* remove the topic3 subscription*/ err = h.Unsubscribe(conn, topic3) assert.NoError(t, err) assert.EqualValues(t, 1, h.SubscriptionTopicCount()) i, err = h.TopicConnectionCount(topic3) assert.Error(t, err) assert.EqualValues(t, 0, i) /* remove the topic4 subscription*/ err = h.Unsubscribe(conn2, topic4) assert.NoError(t, err) assert.EqualValues(t, 0, h.SubscriptionTopicCount()) i, err = h.TopicConnectionCount(topic4) assert.Error(t, err) assert.EqualValues(t, 0, i) /* unsubscribe conn nil */ err = h.Unsubscribe(nil, topic4) assert.Error(t, err) assert.EqualValues(t, 0, h.SubscriptionTopicCount()) /* unsubscribe conn nil */ err = h.Unsubscribe(conn, nil) assert.Error(t, err) assert.EqualValues(t, 0, h.SubscriptionTopicCount()) /* unsubscribe on closed */ err = h.Close() assert.NoError(t, err) err = h.Unsubscribe(conn, topic4) assert.Error(t, err) assert.EqualValues(t, 0, h.SubscriptionTopicCount()) }