From 5fe629519dd5a4aaa43209778d03c024e40f3e1c Mon Sep 17 00:00:00 2001
From: Nikolay Stanchev <ns17@it-innovation.soton.ac.uk>
Date: Tue, 17 Apr 2018 12:23:39 +0100
Subject: [PATCH] converted aggregation scenario to pytest - [Issue #67]

---
 clmctest/monitoring/E2ESim.py          | 119 +++++++++++++++++++++++++
 clmctest/monitoring/conftest.py        |  10 +++
 clmctest/monitoring/test_e2eresults.py |  74 +++++++++++++++
 3 files changed, 203 insertions(+)
 create mode 100644 clmctest/monitoring/E2ESim.py
 create mode 100644 clmctest/monitoring/test_e2eresults.py

diff --git a/clmctest/monitoring/E2ESim.py b/clmctest/monitoring/E2ESim.py
new file mode 100644
index 0000000..53ed774
--- /dev/null
+++ b/clmctest/monitoring/E2ESim.py
@@ -0,0 +1,119 @@
+#!/usr/bin/python3
+"""
+## © University of Southampton IT Innovation Centre, 2018
+##
+## Copyright in this software belongs to University of Southampton
+## IT Innovation Centre of Gamma House, Enterprise Road,
+## Chilworth Science Park, Southampton, SO16 7NS, UK.
+##
+## This software may not be used, sold, licensed, transferred, copied
+## or reproduced in whole or in part in any manner or form or in or
+## on any media by any person other than in accordance with the terms
+## of the Licence Agreement supplied with the software, or otherwise
+## without the prior written consent of the copyright owners.
+##
+## This software is distributed WITHOUT ANY WARRANTY, without even the
+## implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+## PURPOSE, except where stated in the Licence Agreement supplied with
+## the software.
+##
+##      Created By :            Michael Boniface
+##      Created Date :          15-04-2018
+##      Updated By :            Nikolay Stanchev
+##      Updated Date :          16-04-2018
+##      Created for Project :   FLAME
+"""
+
+
+from influxdb import InfluxDBClient
+
+
+class Simulator(object):
+    """
+    Simualator used to generate E2E measurements.
+    """
+
+    DATABASE = 'E2EMetrics'
+    MINUTE = 60000000000  # a minute in nanoseconds
+    SIMULATION_LENGTH = 22  # simulation time in minutes
+
+    def __init__(self, host, port):
+        """
+        Initialises the simulator by creating a db client object and resetting the database.
+
+        :param host: db host url
+        :param port: db port number
+        """
+
+        self.db_client = InfluxDBClient(host=host, port=port, database=self.DATABASE, timeout=10)
+
+        self.reset_db()
+
+    def reset_db(self):
+        """
+        Reset the database using the already initialised db client object.
+        """
+
+        self.db_client.drop_database(self.DATABASE)
+        self.db_client.create_database(self.DATABASE)
+
+    def aggregate_measurements(self, start_time, end_time, sample_period=2):
+        """
+        Executes a query to aggregate the measurements after the simulation is over.
+        :param start_time: start time of simulation (in nanoseconds)
+        :param end_time: end time of simulation (in nanoseconds)
+        :param sample_period: sample period for grouping (in minutes)
+        :return:
+        """
+
+        query = 'SELECT mean("delay") as "Dnet", mean("response_time") as "Dresponse_time" INTO "E2EMetrics"."autogen"."e2e" from "E2EMetrics"."autogen"."net", "E2EMetrics"."autogen"."service" WHERE time >= {0} and time <= {1} GROUP BY time({2}m) fill(previous)'.format(start_time, end_time, sample_period)
+        self.db_client.query(query=query)
+
+    def run(self):
+        """
+        Runs the simulation.
+        """
+
+        start_time = 1523779200000000  # 15/04/2018, 09:00:00 in nanoseconds
+        sim_time = start_time
+
+        mean_delay_seconds_net = 1  # initial mean network delay
+        mean_delay_seconds_media = 10  # initial mean media service delay
+        sample_period_net = 2  # sample period for reporting network delays (measured in minutes)
+        sample_period_media = 5  # sample period for reporting media service delays (measured in minutes)
+
+        for i in range(0, self.SIMULATION_LENGTH):
+            # net delay
+            if i % sample_period_net == 0:
+                point = [{"measurement": "net",
+                          "fields": {
+                              "delay": mean_delay_seconds_net
+                          },
+                          "time": sim_time
+                          }]
+                self.db_client.write_points(point)
+                # increase the delay by 1 every sample
+                mean_delay_seconds_net += 1
+
+            # service response time
+            if i % sample_period_media == 0:
+                point = [{"measurement": "service",
+                          "fields": {
+                              "response_time": mean_delay_seconds_media
+                          },
+                          "time": sim_time
+                          }]
+                self.db_client.write_points(point)
+
+                # increase the delay by 20 every sample
+                mean_delay_seconds_media += 20
+
+            # increase the time by one minute
+            sim_time += self.MINUTE
+
+        end_time = sim_time - self.MINUTE  # decrement one minute to get the last time a measurement have been reported
+        self.aggregate_measurements(start_time, end_time)
+
+
+if __name__ == "__main__":
+    Simulator('203.0.113.100', 8086).run()
diff --git a/clmctest/monitoring/conftest.py b/clmctest/monitoring/conftest.py
index 69389c9..2d866f2 100644
--- a/clmctest/monitoring/conftest.py
+++ b/clmctest/monitoring/conftest.py
@@ -27,6 +27,8 @@ import yaml
 import pkg_resources
 from influxdb import InfluxDBClient
 from clmctest.monitoring.StreamingSim import Sim
+from clmctest.monitoring.E2ESim import Simulator
+
 
 
 @pytest.fixture(scope="module")
@@ -70,3 +72,11 @@ def simulator(streaming_sim_config):
     simulator.reset()
 
     return simulator
+
+
+@pytest.fixture(scope="module")
+def e2e_simulator(streaming_sim_config):
+
+    simulator = Simulator(streaming_sim_config['hosts'][0]['ip_address'], 8086)
+
+    return simulator
diff --git a/clmctest/monitoring/test_e2eresults.py b/clmctest/monitoring/test_e2eresults.py
new file mode 100644
index 0000000..2feb0e7
--- /dev/null
+++ b/clmctest/monitoring/test_e2eresults.py
@@ -0,0 +1,74 @@
+#!/usr/bin/python3
+"""
+## © University of Southampton IT Innovation Centre, 2018
+##
+## Copyright in this software belongs to University of Southampton
+## IT Innovation Centre of Gamma House, Enterprise Road,
+## Chilworth Science Park, Southampton, SO16 7NS, UK.
+##
+## This software may not be used, sold, licensed, transferred, copied
+## or reproduced in whole or in part in any manner or form or in or
+## on any media by any person other than in accordance with the terms
+## of the Licence Agreement supplied with the software, or otherwise
+## without the prior written consent of the copyright owners.
+##
+## This software is distributed WITHOUT ANY WARRANTY, without even the
+## implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+## PURPOSE, except where stated in the Licence Agreement supplied with
+## the software.
+##
+##      Created By :            Nikolay Stanchev
+##      Created Date :          17-04-2018
+##      Created for Project :   FLAME
+"""
+
+import pytest
+import time
+
+
+class TestE2ESimulation(object):
+    """
+    A testing class used to group all the tests related to the E2E simulation data
+    """
+
+    @pytest.fixture(scope='class', autouse=True)
+    def run_simulator(self, e2e_simulator):
+        print("Running simulation, please wait...")
+        e2e_simulator.run()
+
+        print("Waiting for INFLUX to finish receiving simulation data...")
+        time.sleep(5)  # wait for data to finish arriving at the INFLUX database
+        print("... simulation data fixture finished")
+
+    @pytest.mark.parametrize("query, expected_result", [
+        ('SELECT count(*) FROM "E2EMetrics"."autogen"."net"',
+         {"time": "1970-01-01T00:00:00Z", "count_delay": 11}),
+        ('SELECT count(*) FROM "E2EMetrics"."autogen"."service"',
+         {"time": "1970-01-01T00:00:00Z", "count_response_time": 5}),
+        ('SELECT count(*) FROM "E2EMetrics"."autogen"."e2e"',
+         {"time": "1970-01-01T00:00:00Z", "count_Dnet": 11, "count_Dresponse_time": 11}),
+        ])
+    def test_simulation(self, influx_db, query, expected_result):
+        """
+        This is the entry point of the test. This method will be found and executed when the module is ran using pytest
+
+        :param query: the query to execute (value obtained from the pytest parameter decorator)
+        :param expected_result: the result expected from executing the query (value obtained from the pytest parameter decorator)
+        :param influx_db the import db client fixture - imported from contest.py
+        """
+
+        # pytest automatically goes through all queries under test, declared in the parameters decorator
+        print("\n")  # prints a blank line for formatting purposes
+
+        # the raise_errors=False argument is given so that we could actually test that the DB didn't return any errors instead of raising an exception
+        query_result = influx_db.query(query, raise_errors=False)
+
+        # test the error attribute of the result is None, that is no error is returned from executing the DB query
+        assert query_result.error is None, "An error was encountered while executing query {0}.".format(query)
+
+        # get the dictionary of result points; the next() function just gets the first element of the query results generator (we only expect one item in the generator)
+        actual_result = next(query_result.get_points())
+
+        assert expected_result == actual_result, "E2E Simulation test failure"
+
+        print("Successfully passed test for the following query: {0}".format(query))
-- 
GitLab