From e1249d28e698fc239c6525b9d2f13227445f086f Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Tue, 1 Dec 2020 16:06:18 +0100 Subject: [PATCH 1/2] Fix bug causing test_stop event to be fired twice in master node --- locust/runners.py | 7 ++--- locust/test/test_runners.py | 54 +++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 5 deletions(-) diff --git a/locust/runners.py b/locust/runners.py index 51e0fafbc3..307a3c48c9 100644 --- a/locust/runners.py +++ b/locust/runners.py @@ -575,11 +575,8 @@ def stop(self): self.environment.events.test_stop.fire(environment=self.environment) def quit(self): - if self.state not in [STATE_INIT, STATE_STOPPED, STATE_STOPPING]: - logger.debug("Quitting...") - # fire test_stop event if state isn't already stopped - self.environment.events.test_stop.fire(environment=self.environment) - + self.stop() + logger.debug("Quitting...") for client in self.clients.all: logger.debug("Sending quit message to client %s" % (client.id)) self.server.send_to_client(Message("quit", None, client.id)) diff --git a/locust/test/test_runners.py b/locust/test/test_runners.py index 890d4e969b..86cd0e8320 100644 --- a/locust/test/test_runners.py +++ b/locust/test/test_runners.py @@ -487,6 +487,60 @@ def incr_stats(l): "For some reason the master node's stats has not come in", ) + def test_test_stop_event(self): + class TestUser(User): + wait_time = constant(0.1) + @task + def my_task(l): + pass + + with mock.patch("locust.runners.WORKER_REPORT_INTERVAL", new=0.3): + # start a Master runner + master_env = Environment(user_classes=[TestUser]) + test_stop_count = {"master": 0, "worker": 0} + + @master_env.events.test_stop.add_listener + def _(*args, **kwargs): + test_stop_count["master"] += 1 + + master = master_env.create_master_runner("*", 0) + sleep(0) + # start a Worker runner + worker_env = Environment(user_classes=[TestUser]) + + @worker_env.events.test_stop.add_listener + def _(*args, **kwargs): + test_stop_count["worker"] += 1 + + worker = worker_env.create_worker_runner("127.0.0.1", master.server.port) + + # give worker time to connect + sleep(0.1) + # issue start command that should trigger TestUsers to be spawned in the Workers + master.start(2, spawn_rate=1000) + sleep(0.1) + # check that worker nodes have started locusts + self.assertEqual(2, worker.user_count) + # give time for users to generate stats, and stats to be sent to master + sleep(0.1) + master_env.events.quitting.fire(environment=master_env, reverse=True) + master.quit() + sleep(0.1) + # make sure users are killed + self.assertEqual(0, worker.user_count) + + # check the test_stop event was called one time in master and zero times in workder + self.assertEqual( + 1, + test_stop_count["master"], + "The test_stop event was not called exactly one time in the master node", + ) + self.assertEqual( + 0, + test_stop_count["worker"], + "The test_stop event was called in the worker node", + ) + def test_distributed_shape(self): """ Full integration test that starts both a MasterRunner and three WorkerRunner instances From 15c5ddc5a57053b66255355bb53812774f7d52b5 Mon Sep 17 00:00:00 2001 From: Jonatan Heyman Date: Tue, 1 Dec 2020 16:14:52 +0100 Subject: [PATCH 2/2] Formatting --- locust/test/test_runners.py | 1 + 1 file changed, 1 insertion(+) diff --git a/locust/test/test_runners.py b/locust/test/test_runners.py index 86cd0e8320..4c7690edd0 100644 --- a/locust/test/test_runners.py +++ b/locust/test/test_runners.py @@ -490,6 +490,7 @@ def incr_stats(l): def test_test_stop_event(self): class TestUser(User): wait_time = constant(0.1) + @task def my_task(l): pass