Initial DT workflow

Sample PPPoE-based workflow.
Track the subscriber PPPoE protocols state, authentication and IP address assignement are done via PPPoE protocols (PAP, CHAP, IPCP...).
Work with BNG app running on ONOS that generates events in the bng.pppoe Kafka topic.

Change-Id: Iae57395dcc90d027932c790c1c36d7b3e3f3e19b
diff --git a/xos/synchronizer/test_helpers.py b/xos/synchronizer/test_helpers.py
new file mode 100755
index 0000000..f1f3afa
--- /dev/null
+++ b/xos/synchronizer/test_helpers.py
@@ -0,0 +1,163 @@
+# Copyright 2020-present Open Networking Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+from mock import patch, call, Mock, PropertyMock
+import json
+
+import os, sys
+
+test_path=os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
+
+
+class TestDtHelpers(unittest.TestCase):
+
+    def setUp(self):
+
+        self.sys_path_save = sys.path
+
+        # Setting up the config module
+        from xosconfig import Config
+        config = os.path.join(test_path, "test_config.yaml")
+        Config.clear()
+        Config.init(config, "synchronizer-config-schema.yaml")
+        # END Setting up the config module
+
+        from multistructlog import create_logger
+        self.log = create_logger(Config().get('logging'))
+
+        from xossynchronizer.mock_modelaccessor_build import mock_modelaccessor_config
+        mock_modelaccessor_config(test_path, [("dt-workflow-driver", "dt-workflow-driver.xproto"),
+                                              ("olt-service", "volt.xproto"),
+                                              ("rcord", "rcord.xproto")])
+
+        import xossynchronizer.modelaccessor
+        import mock_modelaccessor
+        reload(mock_modelaccessor) # in case nose2 loaded it in a previous test
+        reload(xossynchronizer.modelaccessor)      # in case nose2 loaded it in a previous test
+
+        from xossynchronizer.modelaccessor import model_accessor
+        from helpers import DtHelpers
+
+        # import all class names to globals
+        for (k, v) in model_accessor.all_model_classes.items():
+            globals()[k] = v
+
+        self.helpers = DtHelpers
+        self.model_accessor = model_accessor
+
+        self._volt = VOLTService()
+        self._volt.id = 1
+
+        self.volt = Service()
+        self.volt.id = 1
+        self.volt.name = "vOLT"
+        self.volt.leaf_model = self._volt
+
+        self.pon_port = PONPort()
+        self.pon_port.port_no = 1234
+
+        self.onu = ONUDevice()
+        self.onu.pon_port = self.pon_port
+        self.onu.serial_number = "BRCM1234"
+
+        self.dt_si = DtWorkflowDriverServiceInstance(
+            serial_number="BRCM1234",
+            owner=self.volt,
+            owner_id=self.volt.id,
+            of_dpid="of:1234"
+        )
+
+        self.whitelist_entry = DtWorkflowDriverWhiteListEntry(
+            serial_number="BRCM1234",
+            owner=self.volt,
+            owner_id=self.volt.id,
+            pon_port_id=1234,
+            device_id="of:1234"
+        )
+
+
+    def tearDown(self):
+        sys.path = self.sys_path_save
+
+    def test_not_in_whitelist(self):
+
+        with patch.object(DtWorkflowDriverWhiteListEntry.objects, "get_items") as whitelist_mock:
+            whitelist_mock.return_value = []
+
+            [res, message] = self.helpers.validate_onu(self.model_accessor, self.log, self.dt_si)
+
+            self.assertFalse(res)
+            self.assertEqual(message, "ONU not found in whitelist")
+
+    def test_wrong_location_port(self):
+        self.pon_port.port_no = 666
+        with patch.object(DtWorkflowDriverWhiteListEntry.objects, "get_items") as whitelist_mock, \
+            patch.object(ONUDevice.objects, "get_items") as onu_mock:
+            whitelist_mock.return_value = [self.whitelist_entry]
+            onu_mock.return_value = [self.onu]
+
+            [res, message] = self.helpers.validate_onu(self.model_accessor, self.log, self.dt_si)
+
+            self.assertFalse(res)
+            self.assertEqual(message, "ONU activated in wrong location")
+
+    def test_wrong_location_device(self):
+        self.dt_si.of_dpid = 666
+        with patch.object(DtWorkflowDriverWhiteListEntry.objects, "get_items") as whitelist_mock, \
+            patch.object(ONUDevice.objects, "get_items") as onu_mock:
+            whitelist_mock.return_value = [self.whitelist_entry]
+            onu_mock.return_value = [self.onu]
+
+            [res, message] = self.helpers.validate_onu(self.model_accessor, self.log, self.dt_si)
+
+            self.assertFalse(res)
+            self.assertEqual(message, "ONU activated in wrong location")
+
+    def test_deferred_validation(self):
+        with patch.object(DtWorkflowDriverWhiteListEntry.objects, "get_items") as whitelist_mock, \
+            patch.object(ONUDevice.objects, "get_items") as onu_mock:
+            whitelist_mock.return_value = [self.whitelist_entry]
+            onu_mock.return_value = []
+
+            with self.assertRaises(Exception) as e:
+                self.helpers.validate_onu(self.model_accessor, self.log, self.dt_si)
+
+            self.assertEqual(e.exception.message, "ONU device %s is not know to XOS yet" % self.dt_si.serial_number)
+
+    def test_validating_onu(self):
+        with patch.object(DtWorkflowDriverWhiteListEntry.objects, "get_items") as whitelist_mock, \
+            patch.object(ONUDevice.objects, "get_items") as onu_mock:
+            whitelist_mock.return_value = [self.whitelist_entry]
+            onu_mock.return_value = [self.onu]
+
+            [res, message] = self.helpers.validate_onu(self.model_accessor, self.log, self.dt_si)
+
+            self.assertTrue(res)
+            self.assertEqual(message, "ONU has been validated")
+
+    def test_validating_onu_lowercase(self):
+        self.whitelist_entry.serial_number = "brcm1234"
+        with patch.object(DtWorkflowDriverWhiteListEntry.objects, "get_items") as whitelist_mock, \
+            patch.object(ONUDevice.objects, "get_items") as onu_mock:
+            whitelist_mock.return_value = [self.whitelist_entry]
+            onu_mock.return_value = [self.onu]
+
+            [res, message] = self.helpers.validate_onu(self.model_accessor, self.log, self.dt_si)
+
+            self.assertTrue(res)
+            self.assertEqual(message, "ONU has been validated")
+
+if __name__ == '__main__':
+    unittest.main()
\ No newline at end of file