예제 #1
0
func TestSubscribersIntegration(t *testing.T) {
	defer testutil.ResetDefaultRegistryHealthCheck()
	defer testutil.EnableDebugForMethod()()

	a := assert.New(t)

	s, cleanup := serviceSetUp(t)
	defer cleanup()

	subscribeMultipleClients(t, s, 4)
	a.Nil(nil)

	restClient := restclient.New(fmt.Sprintf("http://%s/api", s.WebServer().GetAddr()))
	content, err := restClient.GetSubscribers(testTopic)
	a.NoError(err)
	routeParams := make([]*Subscriber, 0)

	err = json.Unmarshal(content, &routeParams)
	a.Equal(4, len(routeParams), "Should have 4 subscribers")
	for i, rp := range routeParams {
		a.Equal(fmt.Sprintf("gcmId%d", i), rp.DeviceToken)
		a.Equal(fmt.Sprintf("user%d", i), rp.UserID)
	}
	a.NoError(err)
}
예제 #2
0
func TestStartServiceModules(t *testing.T) {
	defer testutil.ResetDefaultRegistryHealthCheck()

	a := assert.New(t)

	// when starting a simple valid service
	*Config.KVS = "memory"
	*Config.MS = "file"
	*Config.FCM.Enabled = false
	*Config.APNS.Enabled = false

	// using an available port for http
	testHttpPort++
	logger.WithField("port", testHttpPort).Debug("trying to use HTTP Port")
	*Config.HttpListen = fmt.Sprintf(":%d", testHttpPort)

	s := StartService()

	// then the number and ordering of modules should be correct
	a.Equal(6, len(s.ModulesSortedByStartOrder()))
	var moduleNames []string
	for _, iface := range s.ModulesSortedByStartOrder() {
		name := reflect.TypeOf(iface).String()
		moduleNames = append(moduleNames, name)
	}
	a.Equal("*kvstore.MemoryKVStore *filestore.FileMessageStore *router.router *webserver.WebServer *websocket.WSHandler *rest.RestMessageAPI",
		strings.Join(moduleNames, " "))
}
예제 #3
0
func TestHealthUp(t *testing.T) {
	_, finish := testutil.NewMockCtrl(t)
	defer finish()
	defer testutil.ResetDefaultRegistryHealthCheck()
	a := assert.New(t)

	// given:
	service, _, _, _ := aMockedServiceWithMockedRouterStandalone()
	service = service.HealthEndpoint("/health_url")
	a.Equal(2, len(service.ModulesSortedByStartOrder()))

	// when starting the service
	defer service.Stop()
	service.Start()
	time.Sleep(time.Millisecond * 10)

	// and when I call the health URL
	url := fmt.Sprintf("http://%s/health_url", service.WebServer().GetAddr())
	result, err := http.Get(url)

	// then I get status 200 and JSON: {}
	a.NoError(err)
	body, err := ioutil.ReadAll(result.Body)
	a.NoError(err)
	a.Equal("{}", string(body))
}
예제 #4
0
func TestHealthDown(t *testing.T) {
	ctrl, finish := testutil.NewMockCtrl(t)
	defer finish()
	defer testutil.ResetDefaultRegistryHealthCheck()
	a := assert.New(t)

	// given:
	service, _, _, _ := aMockedServiceWithMockedRouterStandalone()
	service = service.HealthEndpoint("/health_url")
	mockChecker := NewMockChecker(ctrl)
	mockChecker.EXPECT().Check().Return(errors.New("sick")).AnyTimes()

	// when starting the service with a short frequency
	defer service.Stop()
	service.healthFrequency = time.Millisecond * 3
	service.RegisterModules(0, 0, mockChecker)
	a.Equal(3, len(service.ModulesSortedByStartOrder()))

	service.Start()
	time.Sleep(time.Millisecond * 10)

	// and when I can call the health URL
	url := fmt.Sprintf("http://%s/health_url", service.WebServer().GetAddr())
	result, err := http.Get(url)
	// then I receive status 503 and a JSON error message
	a.NoError(err)
	a.Equal(503, result.StatusCode)
	body, err := ioutil.ReadAll(result.Body)
	a.NoError(err)
	a.Equal("{\"*service.MockChecker\":\"sick\"}", string(body))
}
예제 #5
0
func Benchmark_E2E_Fetch_HelloWorld_Messages(b *testing.B) {
	defer testutil.ResetDefaultRegistryHealthCheck()

	a := assert.New(b)
	dir, _ := ioutil.TempDir("", "guble_benchmarking_fetch_test")
	defer os.RemoveAll(dir)

	*Config.HttpListen = "localhost:0"
	*Config.KVS = "memory"
	*Config.MS = "file"
	*Config.StoragePath = dir
	service := StartService()
	defer service.Stop()

	time.Sleep(time.Millisecond * 10)

	// fill the topic
	location := "ws://" + service.WebServer().GetAddr() + "/stream/user/xy"
	c, err := client.Open(location, "http://localhost/", 1000, true)
	a.NoError(err)

	for i := 1; i <= b.N; i++ {
		a.NoError(c.Send("/hello", fmt.Sprintf("Hello %v", i), ""))
		select {
		case <-c.StatusMessages():
			// wait for, but ignore
		case <-time.After(time.Millisecond * 100):
			a.Fail("timeout on send notification")
			return
		}
	}

	start := time.Now()
	b.ResetTimer()
	c.WriteRawMessage([]byte("+ /hello 0 1000000"))
	for i := 1; i <= b.N; i++ {
		select {
		case msg := <-c.Messages():
			a.Equal(fmt.Sprintf("Hello %v", i), msg.BodyAsString())
		case e := <-c.Errors():
			a.Fail(string(e.Bytes()))
			return
		case <-time.After(time.Second):
			a.Fail("timeout on message: " + strconv.Itoa(i))
			return
		}
	}
	b.StopTimer()

	end := time.Now()
	throughput := float64(b.N) / end.Sub(start).Seconds()
	fmt.Printf("\n\tThroughput: %v/sec (%v message in %v)\n", int(throughput), b.N, end.Sub(start))
}
예제 #6
0
func TestStoppingOfModules(t *testing.T) {
	defer testutil.ResetDefaultRegistryHealthCheck()

	var p interface{}
	func() {
		defer func() {
			p = recover()
		}()

		service, _, _, _ := aMockedServiceWithMockedRouterStandalone()
		service.RegisterModules(0, 0, &testStopable{})
		service.Stop()
	}()
	assert.NotNil(t, p)
}
예제 #7
0
func TestStartingOfModules(t *testing.T) {
	defer testutil.ResetDefaultRegistryHealthCheck()

	a := assert.New(t)
	var p interface{}
	func() {
		defer func() {
			p = recover()
		}()

		service, _, _, _ := aMockedServiceWithMockedRouterStandalone()
		service.RegisterModules(0, 0, &testStartable{})
		a.Equal(3, len(service.ModulesSortedByStartOrder()))
		service.Start()
	}()
	a.NotNil(p)
}
예제 #8
0
func TestEndpointRegisterAndServing(t *testing.T) {
	_, finish := testutil.NewMockCtrl(t)
	defer finish()
	defer testutil.ResetDefaultRegistryHealthCheck()
	a := assert.New(t)

	// given:
	service, _, _, _ := aMockedServiceWithMockedRouterStandalone()

	// when I register an endpoint at path /foo
	service.RegisterModules(0, 0, &testEndpoint{})
	a.Equal(3, len(service.ModulesSortedByStartOrder()))
	service.Start()
	defer service.Stop()
	time.Sleep(time.Millisecond * 10)

	// then I can call the handler
	url := fmt.Sprintf("http://%s/foo", service.WebServer().GetAddr())
	result, err := http.Get(url)
	a.NoError(err)
	body := make([]byte, 3)
	result.Body.Read(body)
	a.Equal("bar", string(body))
}
예제 #9
0
func Test_Cluster_Integration(t *testing.T) {
	testutil.SkipIfShort(t)
	defer testutil.ResetDefaultRegistryHealthCheck()

	a := assert.New(t)

	node1 := newTestClusterNode(t, testClusterNodeConfig{
		HttpListen: "localhost:8092",
		NodeID:     1,
		NodePort:   11002,
		Remotes:    "localhost:11002",
	})
	a.NotNil(node1)
	defer node1.cleanup(true)

	node2 := newTestClusterNode(t, testClusterNodeConfig{
		HttpListen: "localhost:8093",
		NodeID:     2,
		NodePort:   11003,
		Remotes:    "localhost:11002",
	})
	a.NotNil(node2)
	defer node2.cleanup(true)

	client1, err := node1.client("user1", 10, false)
	a.NoError(err)

	client2, err := node2.client("user2", 10, false)
	a.NoError(err)

	err = client2.Subscribe("/testTopic/m")
	a.NoError(err)

	client3, err := node1.client("user3", 10, false)
	a.NoError(err)

	numSent := 3
	for i := 0; i < numSent; i++ {
		err := client1.Send("/testTopic/m", "body", "{jsonHeader:1}")
		a.NoError(err)

		err = client3.Send("/testTopic/m", "body", "{jsonHeader:4}")
		a.NoError(err)
	}

	breakTimer := time.After(3 * time.Second)
	numReceived := 0
	idReceived := make(map[uint64]bool)

	// see if the correct number of messages arrived at the other client, before timeout is reached
WAIT:
	for {
		select {
		case incomingMessage := <-client2.Messages():
			numReceived++
			logger.WithFields(log.Fields{
				"nodeID":            incomingMessage.NodeID,
				"path":              incomingMessage.Path,
				"incomingMsgUserId": incomingMessage.UserID,
				"headerJson":        incomingMessage.HeaderJSON,
				"body":              incomingMessage.BodyAsString(),
				"numReceived":       numReceived,
			}).Info("Client2 received a message")

			a.Equal(protocol.Path("/testTopic/m"), incomingMessage.Path)
			a.Equal("body", incomingMessage.BodyAsString())
			a.True(incomingMessage.ID > 0)
			idReceived[incomingMessage.ID] = true

			if 2*numReceived == numSent {
				break WAIT
			}

		case <-breakTimer:
			break WAIT
		}
	}
}
예제 #10
0
func TestThroughput(t *testing.T) {
	//testutil.EnableDebugForMethod()
	defer testutil.ResetDefaultRegistryHealthCheck()

	dir, _ := ioutil.TempDir("", "guble_benchmarking_test")
	defer os.RemoveAll(dir)

	*config.HttpListen = "localhost:0"
	*config.KVS = "memory"
	*config.MS = "file"
	*config.StoragePath = dir

	service := StartService()
	defer func() {
		service.Stop()
	}()
	time.Sleep(time.Millisecond * 10)

	testgroupCount := 4
	messagesPerGroup := 100
	log.Printf("init the %v testgroups", testgroupCount)
	testgroups := make([]*testgroup, testgroupCount, testgroupCount)
	for i := range testgroups {
		testgroups[i] = newTestgroup(t, i, service.WebServer().GetAddr(), messagesPerGroup)
	}

	// init test
	log.Print("init the testgroups")
	for i := range testgroups {
		testgroups[i].Init()
	}

	defer func() {
		// cleanup tests
		log.Print("cleanup the testgroups")
		for i := range testgroups {
			testgroups[i].Clean()
		}
	}()

	// start test
	log.Print("start the testgroups")
	start := time.Now()
	for i := range testgroups {
		go testgroups[i].Start()
	}

	log.Print("wait for finishing")
	timeout := time.After(time.Second * 60)
	for i, test := range testgroups {
		//fmt.Printf("wating for test %v\n", i)
		select {
		case successFlag := <-test.done:
			if !successFlag {
				t.Logf("testgroup %v returned with error", i)
				t.FailNow()
				return
			}
		case <-timeout:
			t.Log("timeout. testgroups not ready before timeout")
			t.Fail()
			return
		}
	}

	end := time.Now()
	totalMessages := testgroupCount * messagesPerGroup
	throughput := float64(totalMessages) / end.Sub(start).Seconds()
	log.Printf("finished! Throughput: %v/sec (%v message in %v)", int(throughput), totalMessages, end.Sub(start))
}
예제 #11
0
func throughputSend(b *testing.B, nWorkers int, sampleSend func(c client.Client) error) float64 {
	//testutil.EnableDebugForMethod()
	fmt.Printf("b.N=%v\n", b.N)
	defer testutil.ResetDefaultRegistryHealthCheck()
	a := assert.New(b)

	dir, errTempDir := ioutil.TempDir("", "guble_benchmarking_gcm_test")
	defer func() {
		errRemove := os.RemoveAll(dir)
		if errRemove != nil {
			log.WithFields(log.Fields{
				"module": "testing",
				"err":    errRemove,
			}).Error("Could not remove directory")
		}
	}()
	a.NoError(errTempDir)

	*config.HttpListen = "localhost:0"
	*config.KVS = "memory"
	*config.MS = "file"
	*config.StoragePath = dir
	*config.GCM.Enabled = true
	*config.GCM.APIKey = "WILL BE OVERWRITTEN"
	*config.GCM.Workers = nWorkers

	service := StartService()

	log.WithFields(log.Fields{
		"module": "testing",
	}).Debug("Overwriting the GCM Sender with a MocK")

	gcmConnector, ok := service.Modules()[4].(*gcm.GCMConnector)
	a.True(ok, "Modules[4] should be of type GCMConnector")
	gcmConnector.Sender = testutil.CreateGcmSender(
		testutil.CreateRoundTripperWithJsonResponse(http.StatusOK, testutil.CorrectGcmResponseMessageJSON, nil))

	gomaxprocs := runtime.GOMAXPROCS(0)
	clients := make([]client.Client, 0, gomaxprocs)
	for clientID := 0; clientID < gomaxprocs; clientID++ {
		location := "ws://" + service.WebServer().GetAddr() + "/stream/user/" + strconv.Itoa(clientID)
		client, err := client.Open(location, "http://localhost/", 1000, true)
		a.NoError(err)
		clients = append(clients, client)
	}

	// create a topic
	url := fmt.Sprintf("http://%s/gcm/0/gcmId0/subscribe/topic", service.WebServer().GetAddr())
	response, errPost := http.Post(url, "text/plain", bytes.NewBufferString(""))
	a.NoError(errPost)
	a.Equal(response.StatusCode, 200)
	body, errReadAll := ioutil.ReadAll(response.Body)
	a.NoError(errReadAll)
	a.Equal("registered: /topic\n", string(body))

	log.WithFields(log.Fields{
		"module": "testing",
	}).Debug("Overwriting the GCM Sender with a MocK")

	start := time.Now()
	b.ResetTimer()

	log.WithFields(log.Fields{
		"module": "testing",
	}).Debug("Sending multiple messages from each client in separate goroutines")

	var wg sync.WaitGroup
	wg.Add(gomaxprocs)
	for _, c := range clients {
		go func(c client.Client) {
			defer wg.Done()
			for i := 0; i < b.N; i++ {
				a.NoError(sampleSend(c))
			}
		}(c)
	}
	wg.Wait()

	// stop service (and wait for all the messages to be processed during the given grace period)
	err := service.Stop()
	a.Nil(err)

	end := time.Now()
	b.StopTimer()

	return float64(b.N*gomaxprocs) / end.Sub(start).Seconds()
}
예제 #12
0
func (params *benchParams) throughputFCM() {
	defer testutil.ResetDefaultRegistryHealthCheck()
	a := assert.New(params)

	dir, errTempDir := ioutil.TempDir("", "guble_benchmarking_fcm_test")
	a.NoError(errTempDir)

	*Config.HttpListen = "localhost:0"
	*Config.KVS = "memory"
	*Config.MS = "file"
	*Config.StoragePath = dir
	*Config.FCM.Enabled = true
	*Config.FCM.APIKey = "WILL BE OVERWRITTEN"
	*Config.FCM.Workers = params.workers

	params.service = StartService()

	var fcmConn connector.ResponsiveConnector
	var ok bool
	for _, iface := range params.service.ModulesSortedByStartOrder() {
		fcmConn, ok = iface.(connector.ResponsiveConnector)
		if ok {
			break
		}
	}
	if fcmConn == nil {
		a.FailNow("There should be a module of type: FCM Connector")
	}

	params.receiveC = make(chan bool)
	sender, err := fcm.CreateFcmSender(fcm.SuccessFCMResponse, params.receiveC, params.timeout)
	a.NoError(err)
	fcmConn.SetSender(sender)

	urlFormat := fmt.Sprintf("http://%s/fcm/%%d/gcmId%%d/subscribe/%%s", params.service.WebServer().GetAddr())
	for i := 1; i <= params.subscriptions; i++ {
		// create FCM subscription
		response, errPost := http.Post(
			fmt.Sprintf(urlFormat, i, i, strings.TrimPrefix(testTopic, "/")),
			"text/plain",
			bytes.NewBufferString(""),
		)
		a.NoError(errPost)
		a.Equal(response.StatusCode, 200)

		body, errReadAll := ioutil.ReadAll(response.Body)
		a.NoError(errReadAll)
		a.Equal("{\"subscribed\":\"/topic\"}", string(body))
	}

	clients := params.createClients()

	// Report allocations also
	params.ReportAllocs()

	expectedMessagesNumber := params.N * params.clients * params.subscriptions
	logger.WithFields(log.Fields{
		"expectedMessagesNumber": expectedMessagesNumber,
		"N": params.N,
	}).Info("Expecting messages")
	params.wg.Add(expectedMessagesNumber)

	// start the receive loop (a select on receiveC and doneC)
	params.doneC = make(chan struct{})
	params.receiveLoop()

	params.ResetTimer()

	// send all messages, or fail on any error
	for _, cl := range clients {
		go func(cl client.Client) {
			for i := 0; i < params.N; i++ {
				err := params.sender(cl)
				if err != nil {
					a.FailNow("Message could not be sent")
				}
				params.sent++
			}
		}(cl)
	}

	// wait to receive all messages
	params.wg.Wait()

	// stop timer after the actual test
	params.StopTimer()

	close(params.doneC)
	a.NoError(params.service.Stop())
	params.service = nil
	close(params.receiveC)
	errRemove := os.RemoveAll(dir)
	if errRemove != nil {
		logger.WithError(errRemove).WithField("module", "testing").Error("Could not remove directory")
	}
}
예제 #13
0
func TestThroughput(t *testing.T) {
	// TODO: We disabled this test because the receiver implementation of fetching messages
	// should be reimplemented according to the new message store
	testutil.SkipIfDisabled(t)
	testutil.SkipIfShort(t)
	defer testutil.ResetDefaultRegistryHealthCheck()

	dir, _ := ioutil.TempDir("", "guble_benchmarking_test")

	*Config.HttpListen = "localhost:0"
	*Config.KVS = "memory"
	*Config.MS = "file"
	*Config.StoragePath = dir

	service := StartService()

	testgroupCount := 4
	messagesPerGroup := 100
	log.Printf("init the %v testgroups", testgroupCount)
	testgroups := make([]*testgroup, testgroupCount, testgroupCount)
	for i := range testgroups {
		testgroups[i] = newTestgroup(t, i, service.WebServer().GetAddr(), messagesPerGroup)
	}

	// init test
	log.Print("init the testgroups")
	for i := range testgroups {
		testgroups[i].Init()
	}

	defer func() {
		// cleanup tests
		log.Print("cleanup the testgroups")
		for i := range testgroups {
			testgroups[i].Clean()
		}

		service.Stop()

		os.RemoveAll(dir)
	}()

	// start test
	log.Print("start the testgroups")
	start := time.Now()
	for i := range testgroups {
		go testgroups[i].Start()
	}

	log.Print("wait for finishing")
	for i, test := range testgroups {
		select {
		case successFlag := <-test.done:
			if !successFlag {
				t.Logf("testgroup %v returned with error", i)
				t.FailNow()
				return
			}
		case <-time.After(time.Second * 20):
			t.Log("timeout. testgroups not ready before timeout")
			t.Fail()
			return
		}
	}

	end := time.Now()
	totalMessages := testgroupCount * messagesPerGroup
	throughput := float64(totalMessages) / end.Sub(start).Seconds()
	log.Printf("finished! Throughput: %v/sec (%v message in %v)", int(throughput), totalMessages, end.Sub(start))

	time.Sleep(time.Second * 1)
}
예제 #14
0
// Test that restarting the service continues to fetch messages from store for a subscription from lastID
func TestFCMRestart(t *testing.T) {
	// defer testutil.EnableDebugForMethod()()
	defer testutil.ResetDefaultRegistryHealthCheck()

	a := assert.New(t)

	receiveC := make(chan bool)
	s, cleanup := serviceSetUp(t)
	defer cleanup()

	assertMetrics(a, s, expectedValues{true, 0, 0, 0})

	var fcmConn connector.ResponsiveConnector
	var ok bool
	for _, iface := range s.ModulesSortedByStartOrder() {
		fcmConn, ok = iface.(connector.ResponsiveConnector)
		if ok {
			break
		}
	}
	a.True(ok, "There should be a module of type FCMConnector")

	// add a high timeout so the messages are processed slow
	sender, err := fcm.CreateFcmSender(fcm.SuccessFCMResponse, receiveC, 10*time.Millisecond)
	a.NoError(err)
	fcmConn.SetSender(sender)

	// create subscription on topic
	subscriptionSetUp(t, s)

	assertMetrics(a, s, expectedValues{true, 0, 1, 1})

	c := clientSetUp(t, s)

	// send 3 messages in the router but read only one and close the service
	for i := 0; i < 3; i++ {
		c.Send(testTopic, "dummy body", "{dummy: value}")
	}

	// receive one message only from FCM
	select {
	case <-receiveC:
	case <-time.After(timeoutForOneMessage):
		a.Fail("Initial FCM message not received")
	}

	assertMetrics(a, s, expectedValues{false, 1, 1, 1})
	close(receiveC)
	// restart the service
	a.NoError(s.Stop())

	// remake the sender
	receiveC = make(chan bool)
	sender, err = fcm.CreateFcmSender(fcm.SuccessFCMResponse, receiveC, 10*time.Millisecond)
	a.NoError(err)
	fcmConn.SetSender(sender)

	time.Sleep(50 * time.Millisecond)
	testutil.ResetDefaultRegistryHealthCheck()
	a.NoError(s.Start())

	//TODO Cosmin Bogdan add 2 calls to assertMetrics before and after the next block

	// read the other 2 messages
	for i := 0; i < 1; i++ {
		select {
		case <-receiveC:
		case <-time.After(2 * timeoutForOneMessage):
			a.Fail("FCM message not received")
		}
	}
}
예제 #15
0
func (params *benchParams) throughputAPNS() {
	defer testutil.EnableDebugForMethod()()
	_, finish := testutil.NewMockBenchmarkCtrl(params.B)
	defer finish()
	defer testutil.ResetDefaultRegistryHealthCheck()
	a := assert.New(params)

	dir, errTempDir := ioutil.TempDir("", "guble_benchmarking_apns_test")
	a.NoError(errTempDir)

	*Config.HttpListen = "localhost:0"
	*Config.KVS = "memory"
	*Config.MS = "file"
	*Config.StoragePath = dir
	*Config.APNS.Enabled = true
	*Config.APNS.AppTopic = "app.topic"
	*Config.APNS.Prefix = "/apns/"

	params.receiveC = make(chan bool)
	CreateModules = createModulesWebsocketAndMockAPNSPusher(params.receiveC, params.timeout)

	params.service = StartService()

	var apnsConn connector.ResponsiveConnector
	var ok bool
	for _, iface := range params.service.ModulesSortedByStartOrder() {
		apnsConn, ok = iface.(connector.ResponsiveConnector)
		if ok {
			break
		}
	}
	if apnsConn == nil {
		a.FailNow("There should be a module of type: APNS Connector")
	}

	urlFormat := fmt.Sprintf("http://%s/apns/apns-%%d/%%d/%%s", params.service.WebServer().GetAddr())
	for i := 1; i <= params.subscriptions; i++ {
		// create APNS subscription
		response, errPost := http.Post(
			fmt.Sprintf(urlFormat, i, i, strings.TrimPrefix(testTopic, "/")),
			"text/plain",
			bytes.NewBufferString(""),
		)
		a.NoError(errPost)
		a.Equal(response.StatusCode, 200)

		body, errReadAll := ioutil.ReadAll(response.Body)
		a.NoError(errReadAll)
		a.Equal("{\"subscribed\":\"/topic\"}", string(body))
	}

	clients := params.createClients()

	// Report allocations also
	params.ReportAllocs()

	expectedMessagesNumber := params.N * params.clients * params.subscriptions
	logger.WithFields(log.Fields{
		"expectedMessagesNumber": expectedMessagesNumber,
		"b.N": params.N,
	}).Info("Expecting messages")
	params.wg.Add(expectedMessagesNumber)

	// start the receive loop (a select on receiveC and doneC)
	params.doneC = make(chan struct{})
	params.receiveLoop()

	params.ResetTimer()

	// send all messages, or fail on any error
	for _, cl := range clients {
		go func(cl client.Client) {
			for i := 0; i < params.N; i++ {
				err := params.sender(cl)
				if err != nil {
					a.FailNow("Message could not be sent")
				}
				params.sent++
			}
		}(cl)
	}

	// wait to receive all messages
	params.wg.Wait()

	// stop timer after the actual test
	params.StopTimer()

	close(params.doneC)

	a.NoError(params.service.Stop())
	params.service = nil
	close(params.receiveC)
	errRemove := os.RemoveAll(dir)
	if errRemove != nil {
		logger.WithError(errRemove).WithField("module", "testing").Error("Could not remove directory")
	}
}