Make GenericTrafficGen class abstract 39/47339/2
authorRodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
Thu, 16 Nov 2017 08:56:56 +0000 (08:56 +0000)
committerRodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
Fri, 17 Nov 2017 14:52:12 +0000 (14:52 +0000)
GenericTrafficGen class is now an abstract class. Only optional methods
are implemented.
  - 'run_traffic' and 'terminate' are mandatory.
  - 'listen_traffic', 'verify_traffic' and 'wait_for_instance' are
    optional. By default these methods doesn't execute any action.

JIRA: YARDSTICK-853

Change-Id: I2befdaa337af79cc2364bdd7c66183c31c5ab69a
Signed-off-by: Rodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
tests/unit/network_services/vnf_generic/vnf/test_base.py
tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py
yardstick/network_services/vnf_generic/vnf/base.py
yardstick/network_services/vnf_generic/vnf/sample_vnf.py
yardstick/network_services/vnf_generic/vnf/tg_ixload.py
yardstick/network_services/vnf_generic/vnf/tg_ping.py
yardstick/network_services/vnf_generic/vnf/tg_prox.py
yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
yardstick/network_services/vnf_generic/vnf/tg_trex.py

index 478ce18..f812d67 100644 (file)
@@ -243,31 +243,13 @@ class TestGenericVNF(unittest.TestCase):
 
 
 class TestGenericTrafficGen(unittest.TestCase):
-    def test___init__(self):
-        vnfd = TestGenericVNF.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        generic_traffic_gen = GenericTrafficGen('vnf1', vnfd)
-        assert generic_traffic_gen.name == "vnf1"
-
-    def test_listen_traffic(self):
-        vnfd = TestGenericVNF.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        generic_traffic_gen = GenericTrafficGen('vnf1', vnfd)
-        traffic_profile = {}
-        self.assertIsNone(generic_traffic_gen.listen_traffic(traffic_profile))
-
-    def test_run_traffic(self):
-        vnfd = TestGenericVNF.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        generic_traffic_gen = GenericTrafficGen('vnf1', vnfd)
-        traffic_profile = {}
-        self.assertRaises(NotImplementedError,
-                          generic_traffic_gen.run_traffic, traffic_profile)
-
-    def test_terminate(self):
-        vnfd = TestGenericVNF.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        generic_traffic_gen = GenericTrafficGen('vnf1', vnfd)
-        self.assertRaises(NotImplementedError, generic_traffic_gen.terminate)
 
-    def test_verify_traffic(self):
+    def test_definition(self):
+        """Make sure that the abstract class cannot be instantiated"""
         vnfd = TestGenericVNF.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        generic_traffic_gen = GenericTrafficGen('vnf1', vnfd)
-        traffic_profile = {}
-        self.assertIsNone(generic_traffic_gen.verify_traffic(traffic_profile))
+        name = 'vnf1'
+        with self.assertRaises(TypeError) as exc:
+            GenericTrafficGen(name, vnfd)
+        msg = ("Can't instantiate abstract class GenericTrafficGen with "
+               "abstract methods run_traffic, terminate")
+        self.assertEqual(msg, str(exc.exception))
index 57f9fac..85b10c5 100644 (file)
@@ -2022,55 +2022,32 @@ class TestSampleVNFTrafficGen(unittest.TestCase):
 
         sample_vnf_tg.terminate()
 
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.LOG')
-    def test_wait_for_instantiate(self, mock_logger, mock_time):
+    def test__wait_for_process(self):
         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0)
-        sample_vnf_tg._check_status = mock.Mock(side_effect=iter([1, 0]))
-        sample_vnf_tg._tg_process = mock.Mock()
-        sample_vnf_tg._tg_process.is_alive.return_value = True
-        sample_vnf_tg._tg_process.exitcode = 234
-
-        self.assertEqual(sample_vnf_tg.wait_for_instantiate(), 234)
-
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.LOG')
-    def test_wait_for_instantiate_not_alive(self, mock_logger, mock_time):
+        with mock.patch.object(sample_vnf_tg, '_check_status',
+                               return_value=0) as mock_status, \
+                mock.patch.object(sample_vnf_tg, '_tg_process') as mock_proc:
+            mock_proc.is_alive.return_value = True
+            mock_proc.exitcode = 234
+            self.assertEqual(sample_vnf_tg._wait_for_process(), 234)
+            mock_proc.is_alive.assert_called_once()
+            mock_status.assert_called_once()
+
+    def test__wait_for_process_not_alive(self):
         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0)
-        sample_vnf_tg._check_status = mock.Mock(return_value=1)
-        sample_vnf_tg._tg_process = mock.Mock()
-        sample_vnf_tg._tg_process.is_alive.side_effect = iter([True, False])
-        sample_vnf_tg._tg_process.exitcode = 234
-
-        with self.assertRaises(RuntimeError):
-            sample_vnf_tg.wait_for_instantiate()
-
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.LOG')
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.Process')
-    def test_wait_for_instantiate_delayed(self, mock_process, mock_logger, mock_time):
-        class MockClientStarted(mock.Mock):
-
-            def __init__(self, *args, **kwargs):
-                super(MockClientStarted, self).__init__(*args, **kwargs)
-                self.iter = iter([0, 0, 1])
-
-            @property
-            def value(self):
-                return next(self.iter)
-
-        mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
-        mock_traffic_profile.get_traffic_definition.return_value = "64"
-        mock_traffic_profile.execute_traffic.return_value = "64"
-        mock_traffic_profile.params = self.TRAFFIC_PROFILE
+        with mock.patch.object(sample_vnf_tg, '_tg_process') as mock_proc:
+            mock_proc.is_alive.return_value = False
+            self.assertRaises(RuntimeError, sample_vnf_tg._wait_for_process)
+            mock_proc.is_alive.assert_called_once()
 
+    def test__wait_for_process_delayed(self):
         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0)
-        sample_vnf_tg._check_status = mock.Mock(side_effect=iter([1, 0]))
-        sample_vnf_tg._tg_process = mock.Mock()
-        sample_vnf_tg._tg_process.is_alive.return_value = True
-        sample_vnf_tg._tg_process.exitcode = 234
-        sample_vnf_tg.resource_helper = mock.Mock()
-        sample_vnf_tg.resource_helper.client_started = MockClientStarted()
-
-        self.assertTrue(sample_vnf_tg.run_traffic(mock_traffic_profile))
-        self.assertEqual(mock_time.sleep.call_count, 2)
+        with mock.patch.object(sample_vnf_tg, '_check_status',
+                               side_effect=[1, 0]) as mock_status, \
+                mock.patch.object(sample_vnf_tg,
+                                  '_tg_process') as mock_proc:
+            mock_proc.is_alive.return_value = True
+            mock_proc.exitcode = 234
+            self.assertEqual(sample_vnf_tg._wait_for_process(), 234)
+            mock_proc.is_alive.assert_has_calls([mock.call(), mock.call()])
+            mock_status.assert_has_calls([mock.call(), mock.call()])
index 7781195..8ed754d 100644 (file)
 # limitations under the License.
 """ Base class implementation for generic vnf implementation """
 
-from __future__ import absolute_import
+import abc
+
 import logging
+import six
 
 from yardstick.network_services.helpers.samplevnf_helper import PortPairs
 
+
 LOG = logging.getLogger(__name__)
 
 
@@ -207,6 +210,7 @@ class GenericVNF(VNFObject):
         raise NotImplementedError()
 
 
+@six.add_metaclass(abc.ABCMeta)
 class GenericTrafficGen(GenericVNF):
     """ Class providing file-like API for generic traffic generator """
 
@@ -215,18 +219,29 @@ class GenericTrafficGen(GenericVNF):
         self.runs_traffic = True
         self.traffic_finished = False
 
+    @abc.abstractmethod
     def run_traffic(self, traffic_profile):
-        """ Generate traffic on the wire according to the given params.
-        Method is non-blocking, returns immediately when traffic process
+        """Generate traffic on the wire according to the given params.
+
+        This method is non-blocking, returns immediately when traffic process
         is running. Mandatory.
 
         :param traffic_profile:
         :return: True/False
         """
-        raise NotImplementedError()
+
+    @abc.abstractmethod
+    def terminate(self):
+        """After this method finishes, all traffic processes should stop.
+
+        Mandatory.
+
+        :return: True/False
+        """
 
     def listen_traffic(self, traffic_profile):
-        """ Listen to traffic with the given parameters.
+        """Listen to traffic with the given parameters.
+
         Method is non-blocking, returns immediately when traffic process
         is running. Optional.
 
@@ -236,16 +251,20 @@ class GenericTrafficGen(GenericVNF):
         pass
 
     def verify_traffic(self, traffic_profile):
-        """ Verify captured traffic after it has ended. Optional.
+        """Verify captured traffic after it has ended.
+
+        Optional.
 
         :param traffic_profile:
         :return: dict
         """
         pass
 
-    def terminate(self):
-        """ After this method finishes, all traffic processes should stop. Mandatory.
+    def wait_for_instantiate(self):
+        """Wait for an instance to load.
+
+        Optional.
 
         :return: True/False
         """
-        raise NotImplementedError()
+        pass
index ff81b5f..20e5895 100644 (file)
@@ -895,10 +895,6 @@ class SampleVNFTrafficGen(GenericTrafficGen):
         self._tg_process = Process(name=name, target=self._start_server)
         self._tg_process.start()
 
-    def wait_for_instantiate(self):
-        # overridden by subclasses
-        return self._wait_for_process()
-
     def _check_status(self):
         raise NotImplementedError
 
@@ -942,24 +938,6 @@ class SampleVNFTrafficGen(GenericTrafficGen):
 
         return self._traffic_process.is_alive()
 
-    def listen_traffic(self, traffic_profile):
-        """ Listen to traffic with the given parameters.
-        Method is non-blocking, returns immediately when traffic process
-        is running. Optional.
-
-        :param traffic_profile:
-        :return: True/False
-        """
-        pass
-
-    def verify_traffic(self, traffic_profile):
-        """ Verify captured traffic after it has ended. Optional.
-
-        :param traffic_profile:
-        :return: dict
-        """
-        pass
-
     def collect_kpi(self):
         # check if the tg processes have exited
         for proc in (self._tg_process, self._traffic_process):
index 612799f..61c0454 100644 (file)
@@ -170,16 +170,9 @@ class IxLoadTrafficGen(SampleVNFTrafficGen):
         self.resource_helper.log()
         self.resource_helper.data = self.resource_helper.make_aggregates()
 
-    def listen_traffic(self, traffic_profile):
-        pass
-
     def instantiate(self, scenario_cfg, context_cfg):
         super(IxLoadTrafficGen, self).instantiate(scenario_cfg, context_cfg)
 
-    def wait_for_instantiate(self):
-        # not needed for Ixload
-        pass
-
     def terminate(self):
         call(["pkill", "-9", "http_ixload.py"])
         super(IxLoadTrafficGen, self).terminate()
index 9cd9f25..30a9178 100644 (file)
@@ -14,7 +14,6 @@
 """ PING acts as traffic generation and vnf definitions based on IETS Spec """
 
 from __future__ import absolute_import
-from __future__ import print_function
 import logging
 import re
 
@@ -135,14 +134,3 @@ class PingTrafficGen(SampleVNFTrafficGen):
         }
 
         self.setup_helper.setup_vnf_environment()
-
-    def wait_for_instantiate(self):
-        pass
-
-    def listen_traffic(self, traffic_profile):
-        """ Not needed for ping
-
-        :param traffic_profile:
-        :return:
-        """
-        pass
index 40eda75..151252c 100644 (file)
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from __future__ import print_function, absolute_import
+from __future__ import absolute_import
 
 import logging
 
@@ -63,9 +63,6 @@ class ProxTrafficGen(SampleVNFTrafficGen):
         self.vpci_if_name_ascending = self._sort_vpci(vnfd)
         self.resource_helper.vpci_if_name_ascending = self._sort_vpci(vnfd)
 
-    def listen_traffic(self, traffic_profile):
-        pass
-
     def terminate(self):
         self._vnf_wrapper.terminate()
         super(ProxTrafficGen, self).terminate()
index 47c5a35..a8b19cf 100644 (file)
@@ -204,13 +204,6 @@ class IxiaTrafficGen(SampleVNFTrafficGen):
     def scale(self, flavor=""):
         pass
 
-    def listen_traffic(self, traffic_profile):
-        pass
-
     def terminate(self):
         self.resource_helper.stop_collect()
         super(IxiaTrafficGen, self).terminate()
-
-    def wait_for_instantiate(self):
-        # not needed for IxNet
-        pass
index 93ba855..4250cb7 100644 (file)
@@ -14,8 +14,6 @@
 """ Trex acts as traffic generation and vnf definitions based on IETS Spec """
 
 from __future__ import absolute_import
-from __future__ import print_function
-
 import logging
 import os
 
@@ -191,8 +189,8 @@ class TrexTrafficGen(SampleVNFTrafficGen):
     def scale(self, flavor=""):
         pass
 
-    def listen_traffic(self, traffic_profile):
-        pass
-
     def terminate(self):
         self.resource_helper.terminate()
+
+    def wait_for_instantiate(self):
+        return self._wait_for_process()