func TestGCMConnector_Check(t *testing.T) {
	ctrl, finish := testutil.NewMockCtrl(t)
	defer finish()
	testutil.EnableDebugForMethod()

	assert := assert.New(t)
	routerMock := NewMockRouter(ctrl)
	routerMock.EXPECT().Subscribe(gomock.Any()).Do(func(route *server.Route) {
		assert.Equal("/gcm/broadcast", string(route.Path))
		assert.Equal("gcm_connector", route.UserID)
		assert.Equal("gcm_connector", route.ApplicationID)
	})

	kvStore := store.NewMemoryKVStore()
	routerMock.EXPECT().KVStore().Return(kvStore, nil)

	gcm, err := NewGCMConnector(routerMock, "/gcm/", "testApi", 1)
	assert.Nil(err)

	err = gcm.Start()
	assert.Nil(err)

	done := make(chan bool, 1)
	mockSender := testutil.CreateGcmSender(testutil.CreateRoundTripperWithJsonResponse(http.StatusOK, testutil.CorrectGcmResponseMessageJSON, done))
	gcm.Sender = mockSender
	err = gcm.Check()
	fmt.Println(err)

	done2 := make(chan bool, 1)
	mockSender2 := testutil.CreateGcmSender(testutil.CreateRoundTripperWithJsonResponse(http.StatusUnauthorized, "", done2))
	gcm.Sender = mockSender2
	err = gcm.Check()
	fmt.Println(err)
}
Beispiel #2
0
func TestPostMessage(t *testing.T) {
	defer initCtrl(t)()

	a := assert.New(t)

	// given:  a rest api with a message sink
	routerMock := NewMockPubSubSource(ctrl)
	routerMock.EXPECT().Subscribe(gomock.Any()).Do(func(route *server.Route) {
		a.Equal("/notifications", string(route.Path))
		a.Equal("marvin", route.UserId)
		a.Equal("gcmId123", route.ApplicationId)
	})

	kvStore := store.NewMemoryKVStore()
	gcm := NewGCMConnector("/gcm/", "testApi")
	gcm.SetRouter(routerMock)
	gcm.SetKVStore(kvStore)

	url, _ := url.Parse("http://localhost/gcm/marvin/gcmId123/subscribe/notifications")
	// and a http context
	req := &http.Request{URL: url}
	w := httptest.NewRecorder()

	params := httprouter.Params{
		httprouter.Param{Key: "userid", Value: "marvin"},
		httprouter.Param{Key: "gcmid", Value: "gcmId123"},
		httprouter.Param{Key: "topic", Value: "/notifications"},
	}

	// when: I POST a message
	gcm.Subscribe(w, req, params)

	// the the result
	a.Equal("registered: /notifications\n", string(w.Body.Bytes()))
}
func TestServeHTTPSuccess(t *testing.T) {
	ctrl, finish := testutil.NewMockCtrl(t)
	defer finish()

	a := assert.New(t)

	// given: a rest api with a message sink
	routerMock := NewMockRouter(ctrl)

	kvStore := store.NewMemoryKVStore()
	routerMock.EXPECT().KVStore().Return(kvStore, nil)

	routerMock.EXPECT().Subscribe(gomock.Any()).Do(func(route *server.Route) {
		a.Equal("/notifications", string(route.Path))
		a.Equal("marvin", route.UserID)
		a.Equal("gcmId123", route.ApplicationID)
	})

	gcm, err := NewGCMConnector(routerMock, "/gcm/", "testApi", 1)
	a.Nil(err)

	url, _ := url.Parse("http://localhost/gcm/marvin/gcmId123/subscribe/notifications")
	// and a http context
	req := &http.Request{URL: url, Method: "POST"}
	w := httptest.NewRecorder()

	// when: I POST a message
	gcm.ServeHTTP(w, req)

	// then
	a.Equal("registered: /notifications\n", string(w.Body.Bytes()))
}
func TestGCMConnector_GetErrorMessageFromGcm(t *testing.T) {
	ctrl, finish := testutil.NewMockCtrl(t)
	defer finish()
	// defer testutil.EnableDebugForMethod()()

	a := assert.New(t)
	routerMock := NewMockRouter(ctrl)
	routerMock.EXPECT().Subscribe(gomock.Any()).Do(func(route *server.Route) {
		a.Equal("/gcm/broadcast", string(route.Path))
		a.Equal("gcm_connector", route.UserID)
		a.Equal("gcm_connector", route.ApplicationID)
	})

	// expect the route unsubscribed from removeSubscription
	routerMock.EXPECT().Unsubscribe(gomock.Any()).Do(func(route *server.Route) {
		a.Equal("/path", string(route.Path))
		a.Equal("id", route.ApplicationID)
	})

	// expect the route subscribe with the new canonicalId from replaceSubscriptionWithCanonicalID
	routerMock.EXPECT().Subscribe(gomock.Any()).Do(func(route *server.Route) {
		a.Equal("/path", string(route.Path))
		a.Equal("marvin", route.UserID)
		a.Equal("gcmCanonicalID", route.ApplicationID)
	})

	kvStore := store.NewMemoryKVStore()
	routerMock.EXPECT().KVStore().Return(kvStore, nil)

	gcm, err := NewGCMConnector(routerMock, "/gcm/", "testApi", 1)
	a.Nil(err)

	err = gcm.Start()
	a.Nil(err)

	done := make(chan bool, 1)
	mockSender := testutil.CreateGcmSender(
		testutil.CreateRoundTripperWithJsonResponse(http.StatusOK, testutil.ErrorResponseMessageJSON, done))
	gcm.Sender = mockSender

	// put a dummy gcm message with minimum information
	msg := &server.MessageForRoute{
		Message: &protocol.Message{
			ID:   uint64(4),
			Body: []byte("{id:id}"),
			Time: 1405544146,
			Path: "/gcm/marvin/gcm124/subscribe/stuff"},
		Route: &server.Route{
			ApplicationID: "id",
			Path:          "/path",
			UserID:        "marvin"}}

	gcm.routerC <- msg
	// expect that the Http Server gives us a malformed message
	<-done
	//wait before closing the gcm connector
	time.Sleep(50 * time.Millisecond)
	err = gcm.Stop()
	a.NoError(err)
}
func TestGcmConnector_StartWithMessageSending(t *testing.T) {
	ctrl, finish := testutil.NewMockCtrl(t)
	defer finish()

	a := assert.New(t)
	routerMock := NewMockRouter(ctrl)
	routerMock.EXPECT().Subscribe(gomock.Any()).Do(func(route *server.Route) {
		a.Equal("/gcm/broadcast", string(route.Path))
		a.Equal("gcm_connector", route.UserID)
		a.Equal("gcm_connector", route.ApplicationID)
	})

	kvStore := store.NewMemoryKVStore()
	routerMock.EXPECT().KVStore().Return(kvStore, nil)

	gcm, err := NewGCMConnector(routerMock, "/gcm/", "testApi", 1)
	a.Nil(err)

	err = gcm.Start()
	a.Nil(err)

	done := make(chan bool, 1)
	mockSender := testutil.CreateGcmSender(
		testutil.CreateRoundTripperWithJsonResponse(http.StatusOK, testutil.CorrectGcmResponseMessageJSON, done))
	gcm.Sender = mockSender

	// put a broadcast message with no recipients and expect to be dropped by
	broadcastMsgWithNoRecipients := &server.MessageForRoute{
		Message: &protocol.Message{
			ID:   uint64(4),
			Body: []byte("{id:id}"),
			Time: 1405544146,
			Path: "/gcm/broadcast"}}
	gcm.routerC <- broadcastMsgWithNoRecipients
	time.Sleep(50 * time.Millisecond)
	// expect that the HTTP Dummy Server to not handle any requests

	// put a dummy gcm message with minimum information
	msgWithNoRecipients := &server.MessageForRoute{
		Message: &protocol.Message{
			ID:   uint64(4),
			Body: []byte("{id:id}"),
			Time: 1405544146,
			Path: "/gcm/marvin/gcm124/subscribe/stuff"},
		Route: &server.Route{ApplicationID: "id"}}
	gcm.routerC <- msgWithNoRecipients
	// expect that the Http Server to give us a malformed message
	<-done

	//wait a little to Stop the GcmConnector
	time.Sleep(50 * time.Millisecond)
	err = gcm.Stop()
	a.NoError(err)
}
Beispiel #6
0
func aMockedService() (*Service, store.KVStore, store.MessageStore, *MockMessageSink, *MockPubSubSource) {
	kvStore := store.NewMemoryKVStore()
	messageStore := store.NewDummyMessageStore()
	messageSink := NewMockMessageSink(ctrl)
	pubSubSource := NewMockPubSubSource(ctrl)
	return NewService("localhost:0", kvStore, messageStore, messageSink, pubSubSource, NewAllowAllAccessManager(true)),
		kvStore,
		messageStore,
		messageSink,
		pubSubSource

}
func TestGCMConnector_GetPrefix(t *testing.T) {
	ctrl, finish := testutil.NewMockCtrl(t)
	defer finish()

	a := assert.New(t)
	routerMock := NewMockRouter(ctrl)
	kvStore := store.NewMemoryKVStore()
	routerMock.EXPECT().KVStore().Return(kvStore, nil)

	gcm, err := NewGCMConnector(routerMock, "/gcm/", "testApi", 1)
	a.Nil(err)
	a.Equal(gcm.GetPrefix(), "/gcm/")
}
func TestGCMConnector_BroadcastMessage(t *testing.T) {
	ctrl, finish := testutil.NewMockCtrl(t)
	defer finish()

	a := assert.New(t)

	routerMock := NewMockRouter(ctrl)

	kvStore := store.NewMemoryKVStore()
	routerMock.EXPECT().KVStore().Return(kvStore, nil)

	routerMock.EXPECT().Subscribe(gomock.Any()).Do(func(route *server.Route) {
		a.Equal("/notifications", string(route.Path))
		a.Equal("marvin", route.UserID)
		a.Equal("gcmId123", route.ApplicationID)
	})

	gcm, err := NewGCMConnector(routerMock, "/gcm/", "testApi", 1)
	a.Nil(err)

	url, _ := url.Parse("http://localhost/gcm/marvin/gcmId123/subscribe/notifications")
	// and a http context
	req := &http.Request{URL: url, Method: "POST"}
	w := httptest.NewRecorder()

	// when: I POST a message
	gcm.ServeHTTP(w, req)

	// then
	a.Equal("registered: /notifications\n", string(w.Body.Bytes()))

	done := make(chan bool, 1)
	mockSender := testutil.CreateGcmSender(
		testutil.CreateRoundTripperWithJsonResponse(http.StatusOK, testutil.CorrectGcmResponseMessageJSON, done))
	gcm.Sender = mockSender

	// put a broadcast message with no recipients and expect to be dropped by
	broadcastMessage := &server.MessageForRoute{
		Message: &protocol.Message{
			ID:   uint64(4),
			Body: []byte("{id:id}"),
			Time: 1405544146,
			Path: "/gcm/broadcast"}}
	gcm.broadcastMessage(broadcastMessage)
	// wait for the message to be processed by http server
	<-done
	//wait before closing the gcm connector
	time.Sleep(50 * time.Millisecond)
	err = gcm.Stop()
	a.Nil(err)
}
Beispiel #9
0
func TestGcmOnlyStartedIfEnabled(t *testing.T) {
	_, finish := testutil.NewMockCtrl(t)
	defer finish()

	a := assert.New(t)

	routerMock, _, _ := initRouterMock()
	routerMock.EXPECT().KVStore().Return(store.NewMemoryKVStore(), nil)

	*config.GCM.Enabled = true
	*config.GCM.APIKey = "xyz"
	a.True(containsGcmModule(CreateModules(routerMock)))

	*config.GCM.Enabled = false
	a.False(containsGcmModule(CreateModules(routerMock)))
}
func TestSaveAndLoadSubscriptions(t *testing.T) {
	ctrl, finish := testutil.NewMockCtrl(t)
	defer finish()

	a := assert.New(t)

	// given: some test routes
	testRoutes := map[string]bool{
		"marvin:/foo:1234": true,
		"zappod:/bar:1212": true,
		"athur:/erde:42":   true,
	}

	routerMock := NewMockRouter(ctrl)

	kvStore := store.NewMemoryKVStore()
	routerMock.EXPECT().KVStore().Return(kvStore, nil)

	routerMock.EXPECT().Subscribe(gomock.Any()).Do(func(route *server.Route) {
		// delete the route from the map, if we got it in the test
		delete(testRoutes, fmt.Sprintf("%v:%v:%v", route.UserID, route.Path, route.ApplicationID))
	}).AnyTimes()

	gcm, err := NewGCMConnector(routerMock, "/gcm/", "testApi", 1)
	a.Nil(err)

	// when: we save the routes
	for k := range testRoutes {
		splitKey := strings.SplitN(k, ":", 3)
		userID := splitKey[0]
		topic := splitKey[1]
		gcmID := splitKey[2]
		gcm.saveSubscription(userID, topic, gcmID)
	}

	// and reload the routes
	gcm.loadSubscriptions()

	time.Sleep(50 * time.Millisecond)

	// then: all expected subscriptions were called
	a.Equal(0, len(testRoutes))
}
Beispiel #11
0
func TestSaveAndLoadSubscriptions(t *testing.T) {
	defer initCtrl(t)()
	defer enableDebugForMethod()()
	a := assert.New(t)

	// given: some test routes
	testRoutes := map[string]bool{
		"marvin:/foo:1234": true,
		"zappod:/bar:1212": true,
		"athur:/erde:42":   true,
	}

	routerMock := NewMockPubSubSource(ctrl)
	routerMock.EXPECT().Subscribe(gomock.Any()).Do(func(route *server.Route) {
		// delte the route from the map, if we got it in the test
		delete(testRoutes, fmt.Sprintf("%v:%v:%v", route.UserId, route.Path, route.ApplicationId))
	}).AnyTimes()

	kvStore := store.NewMemoryKVStore()
	gcm := NewGCMConnector("/gcm/", "testApi")
	gcm.SetRouter(routerMock)
	gcm.SetKVStore(kvStore)

	// when: we save the routes
	for k, _ := range testRoutes {
		splitedKey := strings.SplitN(k, ":", 3)
		userid := splitedKey[0]
		topic := splitedKey[1]
		gcmid := splitedKey[2]
		gcm.saveSubscription(userid, topic, gcmid)
	}

	// and reload the routes
	gcm.loadSubscriptions()

	time.Sleep(time.Millisecond * 100)

	// than: all expected subscriptions were called
	a.Equal(0, len(testRoutes))
}
func TestGCMConnector_Stop(t *testing.T) {
	ctrl, finish := testutil.NewMockCtrl(t)
	defer finish()

	a := assert.New(t)
	routerMock := NewMockRouter(ctrl)
	kvStore := store.NewMemoryKVStore()
	routerMock.EXPECT().KVStore().Return(kvStore, nil)

	gcm, err := NewGCMConnector(routerMock, "/gcm/", "testApi", 1)
	a.Nil(err)

	err = gcm.Stop()
	a.Nil(err)
	a.Equal(len(gcm.stopC), 0, "The Stop Channel should be empty")
	select {
	case _, opened := <-gcm.stopC:
		a.False(opened, "The Stop Channel should be closed")
	default:
		a.Fail("Reading from the Stop Channel should not block")
	}
}
func TestGCMConnector_parseParams(t *testing.T) {
	ctrl, finish := testutil.NewMockCtrl(t)
	defer finish()

	a := assert.New(t)
	routerMock := NewMockRouter(ctrl)
	kvStore := store.NewMemoryKVStore()
	routerMock.EXPECT().KVStore().Return(kvStore, nil)

	gcm, err := NewGCMConnector(routerMock, "/gcm/", "testApi", 1)
	a.Nil(err)

	testCases := []struct {
		urlPath, userID, gcmID, topic, err string
	}{
		{"/gcm/marvin/gcmId123/subscribe/notifications", "marvin", "gcmId123", "/notifications", ""},
		{"/gcm2/marvin/gcmId123/subscribe/notifications", "", "", "", "gcm: GCM request is not starting with gcm prefix"},
		{"/gcm/marvin/gcmId123/subscrib2e/notifications", "", "", "", "gcm: GCM request third param is not subscribe"},
		{"/gcm/marvin/gcmId123subscribenotifications", "", "", "", "gcm: GCM request has wrong number of params"},
		{"/gcm/marvin/gcmId123/subscribe/notifications/alert/", "marvin", "gcmId123", "/notifications/alert", ""},
	}

	for i, c := range testCases {
		userID, gcmID, topic, err := gcm.parseParams(c.urlPath)

		//if error message is present check only the error
		if c.err != "" {
			a.NotNil(err)
			a.EqualError(err, c.err, fmt.Sprintf("Failed on testcase no=%d", i))
		} else {
			a.Equal(userID, c.userID, fmt.Sprintf("Failed on testcase no=%d", i))
			a.Equal(gcmID, c.gcmID, fmt.Sprintf("Failed on testcase no=%d", i))
			a.Equal(topic, c.topic, fmt.Sprintf("Failed on testcase no=%d", i))
			a.Nil(err, fmt.Sprintf("Failed on testcase no=%d", i))
		}
	}
	err = gcm.Stop()
	a.Nil(err)
}
func TestServeHTTPWithErrorCases(t *testing.T) {
	ctrl, finish := testutil.NewMockCtrl(t)
	defer finish()

	a := assert.New(t)

	// given: a rest api with a message sink
	routerMock := NewMockRouter(ctrl)

	kvStore := store.NewMemoryKVStore()
	routerMock.EXPECT().KVStore().Return(kvStore, nil)

	gcm, err := NewGCMConnector(routerMock, "/gcm/", "testApi", 1)
	a.Nil(err)

	url, _ := url.Parse("http://localhost/gcm/marvin/gcmId123/subscribe/notifications")
	// and a http context
	req := &http.Request{URL: url, Method: "GET"}
	w := httptest.NewRecorder()

	// do a GET instead of POST
	gcm.ServeHTTP(w, req)

	// check the result
	a.Equal("Permission Denied\n", string(w.Body.Bytes()))
	a.Equal(w.Code, http.StatusMethodNotAllowed)

	// send a new request with wrong parameters encoding
	req.Method = "POST"
	req.URL, _ = url.Parse("http://localhost/gcm/marvin/gcmId123/subscribe3/notifications")

	w2 := httptest.NewRecorder()
	gcm.ServeHTTP(w2, req)

	a.Equal("Invalid Parameters in request\n", string(w2.Body.Bytes()))
	a.Equal(w2.Code, http.StatusBadRequest)
}
Beispiel #15
0
type Args struct {
	Listen      string `arg:"-l,help: [Host:]Port the address to listen on (:8080)" env:"GUBLE_LISTEN"`
	LogInfo     bool   `arg:"--log-info,help: Log on INFO level (false)" env:"GUBLE_LOG_INFO"`
	LogDebug    bool   `arg:"--log-debug,help: Log on DEBUG level (false)" env:"GUBLE_LOG_DEBUG"`
	StoragePath string `arg:"--storage-path,help: The path for storing messages and key value data if 'file' is enabled (/var/lib/guble)" env:"GUBLE_STORAGE_PATH"`
	KVBackend   string `arg:"--kv-backend,help: The storage backend for the key value store to use: file|memory (file)" env:"GUBLE_KV_BACKEND"`
	MSBackend   string `arg:"--ms-backend,help: The message storage backend : file|memory (file)" env:"GUBLE_MS_BACKEND"`
	GcmEnable   bool   `arg:"--gcm-enable: Enable the Google Cloud Messaging Connector (false)" env:"GUBLE_GCM_ENABLE"`
	GcmApiKey   string `arg:"--gcm-api-key: The Google API Key for Google Cloud Messaging" env:"GUBLE_GCM_API_KEY"`
}

var CreateKVStoreBackend = func(args Args) store.KVStore {
	switch args.KVBackend {
	case "memory":
		return store.NewMemoryKVStore()
	case "file":
		db := store.NewSqliteKVStore(path.Join(args.StoragePath, "kv-store.db"), true)
		if err := db.Open(); err != nil {
			panic(err)
		}
		return db
	default:
		panic(fmt.Errorf("unknown key value backend: %q", args.KVBackend))
	}
}

var CreateMessageStoreBackend = func(args Args) store.MessageStore {
	switch args.MSBackend {
	case "none", "":
		return store.NewDummyMessageStore()
Beispiel #16
0
					"storagePath": *config.StoragePath,
					"err":         err,
				}).Error("Use --storage-path=<path> to override the default location, or create the directory with RW rights.")
			}
			return err
		}
		f.Close()
		os.Remove(testfile)
	}
	return nil
}

var CreateKVStore = func() store.KVStore {
	switch *config.KVS {
	case "memory":
		return store.NewMemoryKVStore()
	case "file":
		db := store.NewSqliteKVStore(path.Join(*config.StoragePath, "kv-store.db"), true)
		if err := db.Open(); err != nil {
			logger.WithField("err", err).Panic("Could not open database connection")
		}
		return db
	default:
		panic(fmt.Errorf("Unknown key-value backend: %q", *config.KVS))
	}
}

var CreateMessageStore = func() store.MessageStore {
	switch *config.MS {
	case "none", "":
		return store.NewDummyMessageStore(store.NewMemoryKVStore())