CORD-1939: support for nose2
modify test cases to be compliant with automation
Cherry-pick from cord-4.1 b641f9060eb912470a284bfd04dd955b031af708

Change-Id: I01914ccfb57979994534c6128bc5ff72ae10f64b
diff --git a/lib/xos-genx/xos-genx-tests/__init__.py b/lib/xos-genx/xos-genx-tests/__init__.py
new file mode 100644
index 0000000..d4e8062
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/__init__.py
@@ -0,0 +1,16 @@
+
+# Copyright 2017-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.
+
+
diff --git a/lib/xos-genx/xos-genx-tests/attics/xosmodel_bottom.py b/lib/xos-genx/xos-genx-tests/attics/xosmodel_bottom.py
new file mode 100644
index 0000000..8e28718
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/attics/xosmodel_bottom.py
@@ -0,0 +1,18 @@
+
+# Copyright 2017-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.
+
+
+def bottom():
+    return 'bottom'
\ No newline at end of file
diff --git a/lib/xos-genx/xos-genx-tests/attics/xosmodel_header.py b/lib/xos-genx/xos-genx-tests/attics/xosmodel_header.py
new file mode 100644
index 0000000..044eb4e
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/attics/xosmodel_header.py
@@ -0,0 +1,18 @@
+
+# Copyright 2017-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.
+
+
+def header():
+    return 'header'
\ No newline at end of file
diff --git a/lib/xos-genx/xos-genx-tests/attics/xosmodel_model.py b/lib/xos-genx/xos-genx-tests/attics/xosmodel_model.py
new file mode 100644
index 0000000..ca48b14
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/attics/xosmodel_model.py
@@ -0,0 +1,18 @@
+
+# Copyright 2017-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.
+
+
+def model():
+    return 'model'
\ No newline at end of file
diff --git a/lib/xos-genx/xos-genx-tests/attics/xosmodel_top.py b/lib/xos-genx/xos-genx-tests/attics/xosmodel_top.py
new file mode 100644
index 0000000..2d0adcb
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/attics/xosmodel_top.py
@@ -0,0 +1,18 @@
+
+# Copyright 2017-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.
+
+
+def top():
+    return 'top'
\ No newline at end of file
diff --git a/lib/xos-genx/xos-genx-tests/counts b/lib/xos-genx/xos-genx-tests/counts
new file mode 100755
index 0000000..8ab44d4
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/counts
@@ -0,0 +1,34 @@
+#!/usr/bin/python
+
+import core.models
+import inspect
+from core.models import XOSBase, PlModelMixIn
+import pdb
+
+def count(lst):
+    c = 0
+    for l in lst[0]:
+       ll = l.lstrip()
+       if (ll and not ll.startswith('#') and ll.rstrip()!='pass' and 'ModelLink' not in ll and 'CHOICES' not in ll):
+           c+=1
+    return c
+
+def is_model_class(model):
+    """ Return True if 'model' is something that we're interested in """
+    if not inspect.isclass(model):
+        return False
+    if model.__name__ in ["PlModelMixIn"]:
+        return False
+    bases = inspect.getmro(model)
+    bases = [x.__name__ for x in bases]
+    if ("XOSBase" in bases) or ("PlModelMixIn" in bases):
+        return True
+
+    return False
+
+for a in dir(core.models):
+    x = getattr(core.models,a)
+    if (is_model_class(x)):
+        lines = inspect.getsourcelines(x)
+        print x.__name__,":",count(lines)
+
diff --git a/lib/xos-genx/xos-genx-tests/django_generator_test.py b/lib/xos-genx/xos-genx-tests/django_generator_test.py
new file mode 100644
index 0000000..914c4a3
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/django_generator_test.py
@@ -0,0 +1,43 @@
+
+# Copyright 2017-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
+import os
+from xosgenx.generator import XOSGenerator
+from helpers import FakeArgs
+
+VROUTER_XPROTO = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xproto/vrouterport.xproto")
+
+# Generate Protobuf from Xproto and then parse the resulting Protobuf
+class XProtoProtobufGeneratorTest(unittest.TestCase):
+    def test_proto_generator(self):
+        """
+        [XOS-GenX] Generate DJANGO models, verify Fields and Foreign Keys
+        """
+        args = FakeArgs()
+        args.files = [VROUTER_XPROTO]
+        args.target = 'django.xtarget'
+        output = XOSGenerator.generate(args)
+
+        fields = filter(lambda s:'Field(' in s, output.splitlines())
+        self.assertEqual(len(fields), 2)
+        links = filter(lambda s:'Key(' in s, output.splitlines())
+        self.assertEqual(len(links), 2)
+
+if __name__ == '__main__':
+    unittest.main()
+
+
diff --git a/lib/xos-genx/xos-genx-tests/field_graph_test.py b/lib/xos-genx/xos-genx-tests/field_graph_test.py
new file mode 100644
index 0000000..f7f004c
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/field_graph_test.py
@@ -0,0 +1,92 @@
+
+# Copyright 2017-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 xosgenx.jinja2_extensions import FieldNotFound
+from helpers import FakeArgs, OUTPUT_DIR, XProtoTestHelpers
+from xosgenx.generator import XOSGenerator
+
+class XProtoFieldGraphTest(unittest.TestCase):
+    def test_field_graph(self):
+        xproto = \
+"""
+message VRouterDevice (PlCoreBase){
+     optional string name = 1 [help_text = "device friendly name", max_length = 20, null = True, db_index = False, blank = True, unique_with="openflow_id"];
+     required string openflow_id = 2 [help_text = "device identifier in ONOS", max_length = 20, null = False, db_index = False, blank = False, unique_with="name"];
+     required string config_key = 3 [default = "basic", max_length = 32, blank = False, help_text = "configuration key", null = False, db_index = False, unique_with="driver"];
+     required string driver = 4 [help_text = "driver type", max_length = 32, null = False, db_index = False, blank = False, unique_with="vrouter_service"];
+     required manytoone vrouter_service->VRouterService:devices = 5 [db_index = True, null = False, blank = False];
+     required string A = 6 [unique_with="B"];
+     required string B = 7 [unique_with="C"];
+     required string C = 8 [unique_with="A"];
+     required string D = 9;
+     required string E = 10 [unique_with="F,G"];
+     required string F = 11;
+     required string G = 12;
+}
+"""
+	target = XProtoTestHelpers.write_tmp_target(
+"""
+{{ xproto_field_graph_components(proto.messages.0.fields) }}
+""")
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+        output = XOSGenerator.generate(args)
+        output =  eval(output)
+        self.assertIn({'A','B','C'}, output)
+        self.assertIn({'openflow_id','name'}, output)
+        self.assertIn({'config_key','vrouter_service','driver'}, output)
+        self.assertIn({'E','F','G'}, output)
+        
+        union = reduce(lambda acc,x: acc | x, output)
+        self.assertNotIn('D', union) 
+
+    def test_missing_field(self):
+        xproto = \
+"""
+message VRouterDevice (PlCoreBase){
+     optional string name = 1 [help_text = "device friendly name", max_length = 20, null = True, db_index = False, blank = True, unique_with="hamburger"];
+     required string openflow_id = 2 [help_text = "device identifier in ONOS", max_length = 20, null = False, db_index = False, blank = False, unique_with="name"];
+     required string config_key = 3 [default = "basic", max_length = 32, blank = False, help_text = "configuration key", null = False, db_index = False, unique_with="driver"];
+     required string driver = 4 [help_text = "driver type", max_length = 32, null = False, db_index = False, blank = False, unique_with="vrouter_service"];
+     required manytoone vrouter_service->VRouterService:devices = 5 [db_index = True, null = False, blank = False];
+     required string A = 6 [unique_with="B"];
+     required string B = 7 [unique_with="C"];
+     required string C = 8 [unique_with="A"];
+     required string D = 9;
+}
+"""
+	target = XProtoTestHelpers.write_tmp_target(
+"""
+{{ xproto_field_graph_components(proto.messages.0.fields) }}
+""")
+
+        def generate():
+            args = FakeArgs()
+            args.inputs = xproto
+            args.target = target
+            output = XOSGenerator.generate(args)
+
+        # The following call generates some output, which should disappear
+        # when Matteo merges his refactoring of XOSGenerator.
+        self.assertRaises(FieldNotFound, generate)
+
+if __name__ == '__main__':
+    unittest.main()
+
+
diff --git a/lib/xos-genx/xos-genx-tests/general_security_test.py b/lib/xos-genx/xos-genx-tests/general_security_test.py
new file mode 100644
index 0000000..dbf8538
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/general_security_test.py
@@ -0,0 +1,258 @@
+
+# Copyright 2017-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 xosgenx.generator import XOSGenerator
+from helpers import FakeArgs, XProtoTestHelpers
+
+"""The function below is for eliminating warnings arising due to the missing output_security_check,
+which is generated and loaded dynamically.
+"""
+def output_security_check(x, y):
+    raise Exception("Security enforcer not generated. Test failed.")
+    return False
+
+"""
+The tests below use the Python code target to generate 
+Python security policies, set up an appropriate environment and execute the Python.
+"""
+class XProtoSecurityTest(unittest.TestCase):
+    def setUp(self):
+        self.target = XProtoTestHelpers.write_tmp_target("""
+{% for name, policy in proto.policies.items() %}
+{{ xproto_fol_to_python_test(name, policy, None, '0') }}
+{% endfor %}
+""")
+
+    def test_constant(self):
+        xproto = \
+"""
+    policy output < True >
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def output_security_check(obj, ctx):
+            i1 = True
+            return i1
+        """
+
+        verdict = output_security_check({}, {})
+        self.assertTrue(verdict)
+
+    def test_equal(self):
+        xproto = \
+"""
+    policy output < ctx.user = obj.user >
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def output_security_check(obj, ctx):
+            i1 = (ctx.user == obj.user)
+            return i1
+        """
+
+        obj = FakeArgs()
+	obj.user = 1
+        ctx = FakeArgs()
+	ctx.user = 1
+
+        verdict = output_security_check(obj, ctx)
+
+    def test_call_policy(self):
+        xproto = \
+"""
+    policy sub_policy < ctx.user = obj.user >
+    policy output < *sub_policy(child) >
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+
+        exec(output,globals()) # This loads the generated function, which should look like this:
+
+        """
+        def sub_policy_security_check(obj, ctx):
+            i1 = (ctx.user == obj.user)
+            return i1
+
+        def output_security_check(obj, ctx):
+            if obj.child:
+		i1 = sub_policy_security_check(obj.child, ctx)
+	    else:
+		i1 = True
+	    return i1
+        """
+
+        obj = FakeArgs()
+        obj.child = FakeArgs()
+	obj.child.user = 1
+
+        ctx = FakeArgs()
+	ctx.user = 1
+
+        verdict = output_security_check(obj, ctx)
+        self.assertTrue(verdict)
+
+    def test_call_policy_child_none(self):
+        xproto = \
+"""
+    policy sub_policy < ctx.user = obj.user >
+    policy output < *sub_policy(child) >
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+
+        exec(output,globals()) # This loads the generated function, which should look like this:
+
+        """
+        def sub_policy_security_check(obj, ctx):
+            i1 = (ctx.user == obj.user)
+            return i1
+
+        def output_security_check(obj, ctx):
+            if obj.child:
+		i1 = sub_policy_security_check(obj.child, ctx)
+	    else:
+		i1 = True
+	    return i1
+        """
+
+        obj = FakeArgs()
+        obj.child = None
+
+        ctx = FakeArgs()
+	ctx.user = 1
+
+        verdict = output_security_check(obj, ctx)
+        self.assertTrue(verdict)
+
+
+    def test_bin(self):
+        xproto = \
+"""
+    policy output < ctx.is_admin = True | obj.empty = True>
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+	def output_security_check(obj, ctx):
+	    i2 = (ctx.is_admin == True)
+	    i3 = (obj.empty == True)
+	    i1 = (i2 or i3)
+	    return i1
+        """
+
+        obj = FakeArgs()
+	obj.empty = True
+
+	ctx = FakeArgs()
+	ctx.is_admin = True
+
+        verdict = output_security_check(obj, ctx)
+
+        self.assertTrue(verdict)
+
+        
+    def test_exists(self):
+        xproto = \
+"""
+    policy output < exists Privilege: Privilege.object_id = obj.id >
+"""
+	args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+	def output_security_check(obj, ctx):
+	    i1 = Privilege.objects.filter(object_id=obj.id)
+    	    return i1
+        """
+
+        self.assertTrue(output_security_check is not None)
+	
+    def test_python(self):
+        xproto = \
+"""
+    policy output < {{ "jack" in ["the", "box"] }} = False >
+"""
+	args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+        output = XOSGenerator.generate(args)
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def output_security_check(obj, ctx):
+            i2 = ('jack' in ['the', 'box'])
+            i1 = (i2 == False)
+            return i1
+        """
+
+        self.assertTrue(output_security_check({}, {}) is True)
+
+    def test_forall(self):
+        # This one we only parse
+        xproto = \
+"""
+    policy output < forall Credential: Credential.obj_id = obj_id >
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+        """
+        def output_security_check(obj, ctx):
+            i2 = Credential.objects.filter((~ Q(obj_id=obj_id)))[0]
+            i1 = (not i2)
+            return i1
+        """
+        exec(output)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/lib/xos-genx/xos-genx-tests/general_validation_test.py b/lib/xos-genx/xos-genx-tests/general_validation_test.py
new file mode 100644
index 0000000..fbed567
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/general_validation_test.py
@@ -0,0 +1,259 @@
+
+# Copyright 2017-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 xosgenx.generator import XOSGenerator
+from helpers import FakeArgs, XProtoTestHelpers
+import pdb
+
+"""The function below is for eliminating warnings arising due to the missing policy_output_validator,
+which is generated and loaded dynamically.
+"""
+def policy_output_validator(x, y):
+    raise Exception("Validator not generated. Test failed.")
+    return False
+
+"""
+The tests below use the Python code target to generate 
+Python validation policies, set up an appropriate environment and execute the Python.
+"""
+class XProtoGeneralValidationTest(unittest.TestCase):
+    def setUp(self):
+        self.target = XProtoTestHelpers.write_tmp_target("""
+{% for name, policy in proto.policies.items() %}
+{{ xproto_fol_to_python_validator(name, policy, None, 'Necessary Failure') }}
+{% endfor %}
+""")
+
+    def test_constant(self):
+        xproto = \
+"""
+    policy output < False >
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def policy_output_validator(obj, ctx):
+            i1 = False
+            if (not i1):
+                raise Exception('Necessary Failure')
+        """
+
+        with self.assertRaises(Exception):
+           policy_output_validator({}, {})
+    
+    def test_equal(self):
+        xproto = \
+"""
+    policy output < not (ctx.user = obj.user) >
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def policy_output_validator(obj, ctx):
+            i2 = (ctx.user == obj.user)
+            i1 = (not i2)
+            if (not i1):
+                raise Exception('Necessary Failure')
+        """
+
+        obj = FakeArgs()
+	obj.user = 1
+        ctx = FakeArgs()
+	ctx.user = 1
+
+        with self.assertRaises(Exception):
+           policy_output_validator(obj, ctx)
+
+    def test_equal(self):
+        xproto = \
+"""
+    policy output < not (ctx.user = obj.user) >
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def policy_output_validator(obj, ctx):
+            i2 = (ctx.user == obj.user)
+            i1 = (not i2)
+            if (not i1):
+                raise Exception('Necessary Failure')
+        """
+
+        obj = FakeArgs()
+	obj.user = 1
+        ctx = FakeArgs()
+	ctx.user = 1
+
+        with self.assertRaises(Exception):
+           policy_output_validator(obj, ctx)
+
+    def test_bin(self):
+        xproto = \
+"""
+    policy output < (ctx.is_admin = True | obj.empty = True) | False>
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def policy_output_validator(obj, ctx):
+            i2 = (ctx.is_admin == True)
+            i3 = (obj.empty == True)
+            i1 = (i2 or i3)
+            if (not i1):
+                raise Exception('Necessary Failure')
+        """
+
+        obj = FakeArgs()
+	obj.empty = False
+
+	ctx = FakeArgs()
+	ctx.is_admin = False
+
+        with self.assertRaises(Exception):
+            verdict = policy_output_validator(obj, ctx)
+
+        
+    def test_exists(self):
+        xproto = \
+"""
+    policy output < exists Privilege: Privilege.object_id = obj.id >
+"""
+	args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def policy_output_validator(obj, ctx):
+            i1 = Privilege.objects.filter(Q(object_id=obj.id))[0]
+            if (not i1):
+                raise Exception('Necessary Failure')
+        """
+
+        self.assertTrue(policy_output_validator is not None)
+	
+    def test_python(self):
+        xproto = \
+"""
+    policy output < {{ "jack" in ["the", "box"] }} = True >
+"""
+	args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+        output = XOSGenerator.generate(args)
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def policy_output_validator(obj, ctx):
+            i2 = ('jack' in ['the', 'box'])
+            i1 = (i2 == True)
+            if (not i1):
+                raise Exception('Necessary Failure')
+        """
+
+        with self.assertRaises(Exception):
+            self.assertTrue(policy_output_validator({}, {}) is True)
+
+    def test_call_policy(self):
+        xproto = \
+"""
+    policy sub_policy < ctx.user = obj.user >
+    policy output < *sub_policy(child) >
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+
+        exec(output,globals()) # This loads the generated function, which should look like this:
+
+        """
+        def policy_sub_policy_validator(obj, ctx):
+            i1 = (ctx.user == obj.user)
+            if (not i1):
+                raise ValidationError('Necessary Failure')
+
+        def policy_output_validator(obj, ctx):
+            i1 = policy_sub_policy_validator(obj.child, ctx)
+            if (not i1):
+                raise ValidationError('Necessary Failure')
+        """
+
+        obj = FakeArgs()
+        obj.child = FakeArgs()
+	obj.child.user = 1
+
+        ctx = FakeArgs()
+	ctx.user = 1
+
+        with self.assertRaises(Exception):
+            verdict = policy_output_enforcer(obj, ctx)
+
+    def test_forall(self):
+        # This one we only parse
+        xproto = \
+"""
+    policy output < forall Credential: Credential.obj_id = obj_id >
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+
+        """
+        def policy_output_enforcer(obj, ctx):
+            i2 = Credential.objects.filter((~ Q(obj_id=obj_id)))[0]
+            i1 = (not i2)
+            return i1
+        """
+
+        self.assertIn('policy_output_validator', output)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/lib/xos-genx/xos-genx-tests/graph_test.py b/lib/xos-genx/xos-genx-tests/graph_test.py
new file mode 100644
index 0000000..48978e9
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/graph_test.py
@@ -0,0 +1,317 @@
+
+# Copyright 2017-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 xosgenx.generator import XOSGenerator
+from helpers import FakeArgs, XProtoTestHelpers
+
+class XProtoGraphTests(unittest.TestCase):
+    def test_cross_model(self):
+        target = XProtoTestHelpers.write_tmp_target(
+"""
+  {% for m in proto.messages %}
+  {{ m.name }} {
+  {%- for l in m.links %}
+     {%- if proto.message_table[l.peer.fqn] -%}
+     {%- set model = proto.message_table[l.peer.fqn] %}
+        {% for f in model.fields %}
+        {{ f.type }} {{ f.name }};
+        {% endfor %}
+     {%- endif -%}
+  {% endfor %}
+  }
+  {% endfor %}
+""")
+
+        proto = \
+"""
+message Port (PlCoreBase,ParameterMixin){
+     required manytoone network->Network:links = 1 [db_index = True, null = False, blank = False];
+     optional manytoone instance->Instance:ports = 2 [db_index = True, null = True, blank = True];
+     optional string ip = 3 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     optional string port_id = 4 [help_text = "Neutron port id", max_length = 256, null = True, db_index = False, blank = True];
+     optional string mac = 5 [help_text = "MAC address associated with this port", max_length = 256, null = True, db_index = False, blank = True];
+     required bool xos_created = 6 [default = False, null = False, db_index = False, blank = True];
+}
+
+message Instance (PlCoreBase){
+     optional string instance_id = 1 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance id", null = True, db_index = False];
+     optional string instance_uuid = 2 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance uuid", null = True, db_index = False];
+     required string name = 3 [max_length = 200, content_type = "stripped", blank = False, help_text = "Instance name", null = False, db_index = False];
+     optional string instance_name = 4 [max_length = 200, content_type = "stripped", blank = True, help_text = "OpenStack generated name", null = True, db_index = False];
+     optional string ip = 5 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     required manytoone image->Image:instances = 6 [db_index = True, null = False, blank = False];
+     optional manytoone creator->User:instances = 7 [db_index = True, null = True, blank = True];
+     required manytoone slice->Slice:instances = 8 [db_index = True, null = False, blank = False];
+     required manytoone deployment->Deployment:instance_deployment = 9 [db_index = True, null = False, blank = False];
+     required manytoone node->Node:instances = 10 [db_index = True, null = False, blank = False];
+     required int32 numberCores = 11 [help_text = "Number of cores for instance", default = 0, null = False, db_index = False, blank = False];
+     required manytoone flavor->Flavor:instance = 12 [help_text = "Flavor of this instance", default = "get_default_flavor()", null = False, db_index = True, blank = False];
+     optional string userData = 13 [help_text = "user_data passed to instance during creation", null = True, db_index = False, blank = True];
+     required string isolation = 14 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+     optional string volumes = 15 [help_text = "Comma-separated list of directories to expose to parent context", null = True, db_index = False, blank = True];
+     optional manytoone parent->Instance:instance = 16 [help_text = "Parent Instance for containers nested inside of VMs", null = True, db_index = True, blank = True];
+     required manytomany tags->Tag = 17 [db_index = False, null = False, blank = True];
+}
+
+message Network (PlCoreBase,ParameterMixin) {
+     required string name = 1 [db_index = False, max_length = 32, null = False, blank = False];
+     required manytoone template->NetworkTemplate:network = 2 [db_index = True, null = False, blank = False];
+     required string subnet = 3 [db_index = False, max_length = 32, null = False, blank = True];
+     required string start_ip = 4 [db_index = False, max_length = 32, null = False, blank = True];
+     required string end_ip = 5 [db_index = False, max_length = 32, null = False, blank = True];
+     optional string ports = 6 [db_index = False, max_length = 1024, null = True, blank = True];
+     optional string labels = 7 [db_index = False, max_length = 1024, null = True, blank = True];
+     required manytoone owner->Slice:ownedNetworks = 8 [help_text = "Slice that owns control of this Network", null = False, db_index = True, blank = False];
+     required int32 guaranteed_bandwidth = 9 [default = 0, null = False, db_index = False, blank = False];
+     required bool permit_all_slices = 10 [default = False, null = False, db_index = False, blank = True];
+     optional string topology_parameters = 11 [db_index = False, null = True, blank = True];
+     optional string controller_url = 12 [db_index = False, max_length = 1024, null = True, blank = True];
+     optional string controller_parameters = 13 [db_index = False, null = True, blank = True];
+     optional string network_id = 14 [help_text = "Quantum network", max_length = 256, null = True, db_index = False, blank = True];
+     optional string router_id = 15 [help_text = "Quantum router id", max_length = 256, null = True, db_index = False, blank = True];
+     optional string subnet_id = 16 [help_text = "Quantum subnet id", max_length = 256, null = True, db_index = False, blank = True];
+     required bool autoconnect = 17 [help_text = "This network can be autoconnected to the slice that owns it", default = True, null = False, db_index = False, blank = True];
+     required manytomany permitted_slices->Slice/Network_permitted_slices:availableNetworks = 18 [db_index = False, null = False, blank = True];
+     required manytomany slices->Slice/NetworkSlice:networks = 19 [db_index = False, null = False, blank = True];
+     required manytomany instances->Instance/Port:networks = 20 [db_index = False, null = False, blank = True];
+}
+
+message Slice (PlCoreBase){
+     required string name = 1 [max_length = 80, content_type = "stripped", blank = False, help_text = "The Name of the Slice", null = False, db_index = False];
+     required bool enabled = 2 [help_text = "Status for this Slice", default = True, null = False, db_index = False, blank = True];
+     required bool omf_friendly = 3 [default = False, null = False, db_index = False, blank = True];
+     required string description = 4 [help_text = "High level description of the slice and expected activities", max_length = 1024, null = False, db_index = False, blank = True];
+     required string slice_url = 5 [db_index = False, max_length = 512, null = False, content_type = "url", blank = True];
+     required manytoone site->Site:slices = 6 [help_text = "The Site this Slice belongs to", null = False, db_index = True, blank = False];
+     required int32 max_instances = 7 [default = 10, null = False, db_index = False, blank = False];
+     optional manytoone service->Service:slices = 8 [db_index = True, null = True, blank = True];
+     optional string network = 9 [blank = True, max_length = 256, null = True, db_index = False, choices = "((None, 'Default'), ('host', 'Host'), ('bridged', 'Bridged'), ('noauto', 'No Automatic Networks'))"];
+     optional string exposed_ports = 10 [db_index = False, max_length = 256, null = True, blank = True];
+     optional manytoone serviceClass->ServiceClass:slices = 11 [db_index = True, null = True, blank = True];
+     optional manytoone creator->User:slices = 12 [db_index = True, null = True, blank = True];
+     optional manytoone default_flavor->Flavor:slices = 13 [db_index = True, null = True, blank = True];
+     optional manytoone default_image->Image:slices = 14 [db_index = True, null = True, blank = True];
+     optional manytoone default_node->Node:slices = 15 [db_index = True, null = True, blank = True];
+     optional string mount_data_sets = 16 [default = "GenBank", max_length = 256, content_type = "stripped", blank = True, null = True, db_index = False];
+     required string default_isolation = 17 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+     required manytomany tags->Tag = 18 [db_index = False, null = False, blank = True];
+}
+"""
+
+        args = FakeArgs()
+        args.inputs = proto
+        args.target = target
+        output = XOSGenerator.generate(args)
+        num_semis = output.count(';')
+        self.assertGreater(num_semis, 3) # 3 is the number of links, each of which contains at least one field
+
+    def test_base_class_fields(self):
+        target = \
+"""
+  {% for m in proto.messages %}
+  {{ m.name }} {
+  {%- for l in m.links %}
+     {%- if proto.message_table[l.peer.fqn] -%}
+     {%- set model = proto.message_table[l.peer.fqn] %}
+        {% for f in model.fields %}
+        {{ f.type }} {{ f.name }};
+        {% endfor %}
+     {%- endif -%}
+  {% endfor %}
+  }
+  {% endfor %}
+"""
+        xtarget = XProtoTestHelpers.write_tmp_target(target)
+
+        proto = \
+"""
+message Port (PlCoreBase,ParameterMixin){
+     required manytoone network->Network:links = 1 [db_index = True, null = False, blank = False];
+     optional manytoone instance->Instance:ports = 2 [db_index = True, null = True, blank = True];
+     optional string ip = 3 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     optional string port_id = 4 [help_text = "Neutron port id", max_length = 256, null = True, db_index = False, blank = True];
+     optional string mac = 5 [help_text = "MAC address associated with this port", max_length = 256, null = True, db_index = False, blank = True];
+     required bool xos_created = 6 [default = False, null = False, db_index = False, blank = True];
+}
+
+message Instance (PlCoreBase){
+     optional string instance_id = 1 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance id", null = True, db_index = False];
+     optional string instance_uuid = 2 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance uuid", null = True, db_index = False];
+     required string name = 3 [max_length = 200, content_type = "stripped", blank = False, help_text = "Instance name", null = False, db_index = False];
+     optional string instance_name = 4 [max_length = 200, content_type = "stripped", blank = True, help_text = "OpenStack generated name", null = True, db_index = False];
+     optional string ip = 5 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     required manytoone image->Image:instances = 6 [db_index = True, null = False, blank = False];
+     optional manytoone creator->User:instances = 7 [db_index = True, null = True, blank = True];
+     required manytoone slice->Slice:instances = 8 [db_index = True, null = False, blank = False];
+     required manytoone deployment->Deployment:instance_deployment = 9 [db_index = True, null = False, blank = False];
+     required manytoone node->Node:instances = 10 [db_index = True, null = False, blank = False];
+     required int32 numberCores = 11 [help_text = "Number of cores for instance", default = 0, null = False, db_index = False, blank = False];
+     required manytoone flavor->Flavor:instance = 12 [help_text = "Flavor of this instance", default = "get_default_flavor()", null = False, db_index = True, blank = False];
+     optional string userData = 13 [help_text = "user_data passed to instance during creation", null = True, db_index = False, blank = True];
+     required string isolation = 14 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+     optional string volumes = 15 [help_text = "Comma-separated list of directories to expose to parent context", null = True, db_index = False, blank = True];
+     optional manytoone parent->Instance:instance = 16 [help_text = "Parent Instance for containers nested inside of VMs", null = True, db_index = True, blank = True];
+     required manytomany tags->Tag = 17 [db_index = False, null = False, blank = True];
+}
+
+message Network (PlCoreBase,ParameterMixin) {
+     required string name = 1 [db_index = False, max_length = 32, null = False, blank = False];
+     required manytoone template->NetworkTemplate:network = 2 [db_index = True, null = False, blank = False];
+     required string subnet = 3 [db_index = False, max_length = 32, null = False, blank = True];
+     required string start_ip = 4 [db_index = False, max_length = 32, null = False, blank = True];
+     required string end_ip = 5 [db_index = False, max_length = 32, null = False, blank = True];
+     optional string ports = 6 [db_index = False, max_length = 1024, null = True, blank = True];
+     optional string labels = 7 [db_index = False, max_length = 1024, null = True, blank = True];
+     required manytoone owner->Slice:ownedNetworks = 8 [help_text = "Slice that owns control of this Network", null = False, db_index = True, blank = False];
+     required int32 guaranteed_bandwidth = 9 [default = 0, null = False, db_index = False, blank = False];
+     required bool permit_all_slices = 10 [default = False, null = False, db_index = False, blank = True];
+     optional string topology_parameters = 11 [db_index = False, null = True, blank = True];
+     optional string controller_url = 12 [db_index = False, max_length = 1024, null = True, blank = True];
+     optional string controller_parameters = 13 [db_index = False, null = True, blank = True];
+     optional string network_id = 14 [help_text = "Quantum network", max_length = 256, null = True, db_index = False, blank = True];
+     optional string router_id = 15 [help_text = "Quantum router id", max_length = 256, null = True, db_index = False, blank = True];
+     optional string subnet_id = 16 [help_text = "Quantum subnet id", max_length = 256, null = True, db_index = False, blank = True];
+     required bool autoconnect = 17 [help_text = "This network can be autoconnected to the slice that owns it", default = True, null = False, db_index = False, blank = True];
+     required manytomany permitted_slices->Slice/Network_permitted_slices:availableNetworks = 18 [db_index = False, null = False, blank = True];
+     required manytomany slices->Slice/NetworkSlice:networks = 19 [db_index = False, null = False, blank = True];
+     required manytomany instances->Instance/Port:networks = 20 [db_index = False, null = False, blank = True];
+}
+
+message Slice (PlCoreBase){
+     required string name = 1 [max_length = 80, content_type = "stripped", blank = False, help_text = "The Name of the Slice", null = False, db_index = False];
+     required bool enabled = 2 [help_text = "Status for this Slice", default = True, null = False, db_index = False, blank = True];
+     required bool omf_friendly = 3 [default = False, null = False, db_index = False, blank = True];
+     required string description = 4 [help_text = "High level description of the slice and expected activities", max_length = 1024, null = False, db_index = False, blank = True];
+     required string slice_url = 5 [db_index = False, max_length = 512, null = False, content_type = "url", blank = True];
+     required manytoone site->Site:slices = 6 [help_text = "The Site this Slice belongs to", null = False, db_index = True, blank = False];
+     required int32 max_instances = 7 [default = 10, null = False, db_index = False, blank = False];
+     optional manytoone service->Service:slices = 8 [db_index = True, null = True, blank = True];
+     optional string network = 9 [blank = True, max_length = 256, null = True, db_index = False, choices = "((None, 'Default'), ('host', 'Host'), ('bridged', 'Bridged'), ('noauto', 'No Automatic Networks'))"];
+     optional string exposed_ports = 10 [db_index = False, max_length = 256, null = True, blank = True];
+     optional manytoone serviceClass->ServiceClass:slices = 11 [db_index = True, null = True, blank = True];
+     optional manytoone creator->User:slices = 12 [db_index = True, null = True, blank = True];
+     optional manytoone default_flavor->Flavor:slices = 13 [db_index = True, null = True, blank = True];
+     optional manytoone default_image->Image:slices = 14 [db_index = True, null = True, blank = True];
+     optional manytoone default_node->Node:slices = 15 [db_index = True, null = True, blank = True];
+     optional string mount_data_sets = 16 [default = "GenBank", max_length = 256, content_type = "stripped", blank = True, null = True, db_index = False];
+     required string default_isolation = 17 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+     required manytomany tags->Tag = 18 [db_index = False, null = False, blank = True];
+}
+"""
+
+        args = FakeArgs()
+        args.inputs = proto
+        args.target = xtarget
+        output = XOSGenerator.generate(args)
+
+        num_semis = output.count(';')
+        self.assertGreater(num_semis, 3)
+
+    def test_from_base(self):
+        target = \
+"""
+  {% for f in xproto_base_fields(proto.messages.3, proto.message_table) %}
+        {{ f.type }} {{ f.name }};
+  {% endfor %}
+"""
+        xtarget = XProtoTestHelpers.write_tmp_target(target)
+        proto = \
+"""
+message Port (PlCoreBase,ParameterMixin){
+     required string easter_egg = 1;
+     required manytoone network->Network:links = 1 [db_index = True, null = False, blank = False];
+     optional manytoone instance->Instance:ports = 2 [db_index = True, null = True, blank = True];
+     optional string ip = 3 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     optional string port_id = 4 [help_text = "Neutron port id", max_length = 256, null = True, db_index = False, blank = True];
+     optional string mac = 5 [help_text = "MAC address associated with this port", max_length = 256, null = True, db_index = False, blank = True];
+     required bool xos_created = 6 [default = False, null = False, db_index = False, blank = True];
+}
+
+message Instance (Port){
+     optional string instance_id = 1 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance id", null = True, db_index = False];
+     optional string instance_uuid = 2 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance uuid", null = True, db_index = False];
+     required string name = 3 [max_length = 200, content_type = "stripped", blank = False, help_text = "Instance name", null = False, db_index = False];
+     optional string instance_name = 4 [max_length = 200, content_type = "stripped", blank = True, help_text = "OpenStack generated name", null = True, db_index = False];
+     optional string ip = 5 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     required manytoone image->Image:instances = 6 [db_index = True, null = False, blank = False];
+     optional manytoone creator->User:instances = 7 [db_index = True, null = True, blank = True];
+     required manytoone slice->Slice:instances = 8 [db_index = True, null = False, blank = False];
+     required manytoone deployment->Deployment:instance_deployment = 9 [db_index = True, null = False, blank = False];
+     required manytoone node->Node:instances = 10 [db_index = True, null = False, blank = False];
+     required int32 numberCores = 11 [help_text = "Number of cores for instance", default = 0, null = False, db_index = False, blank = False];
+     required manytoone flavor->Flavor:instance = 12 [help_text = "Flavor of this instance", default = "get_default_flavor()", null = False, db_index = True, blank = False];
+     optional string userData = 13 [help_text = "user_data passed to instance during creation", null = True, db_index = False, blank = True];
+     required string isolation = 14 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+     optional string volumes = 15 [help_text = "Comma-separated list of directories to expose to parent context", null = True, db_index = False, blank = True];
+     optional manytoone parent->Instance:instance = 16 [help_text = "Parent Instance for containers nested inside of VMs", null = True, db_index = True, blank = True];
+     required manytomany tags->Tag = 17 [db_index = False, null = False, blank = True];
+}
+
+message Network (Instance) {
+     required string name = 1 [db_index = False, max_length = 32, null = False, blank = False];
+     required manytoone template->NetworkTemplate:network = 2 [db_index = True, null = False, blank = False];
+     required string subnet = 3 [db_index = False, max_length = 32, null = False, blank = True];
+     required string start_ip = 4 [db_index = False, max_length = 32, null = False, blank = True];
+     required string end_ip = 5 [db_index = False, max_length = 32, null = False, blank = True];
+     optional string ports = 6 [db_index = False, max_length = 1024, null = True, blank = True];
+     optional string labels = 7 [db_index = False, max_length = 1024, null = True, blank = True];
+     required manytoone owner->Slice:ownedNetworks = 8 [help_text = "Slice that owns control of this Network", null = False, db_index = True, blank = False];
+     required int32 guaranteed_bandwidth = 9 [default = 0, null = False, db_index = False, blank = False];
+     required bool permit_all_slices = 10 [default = False, null = False, db_index = False, blank = True];
+     optional string topology_parameters = 11 [db_index = False, null = True, blank = True];
+     optional string controller_url = 12 [db_index = False, max_length = 1024, null = True, blank = True];
+     optional string controller_parameters = 13 [db_index = False, null = True, blank = True];
+     optional string network_id = 14 [help_text = "Quantum network", max_length = 256, null = True, db_index = False, blank = True];
+     optional string router_id = 15 [help_text = "Quantum router id", max_length = 256, null = True, db_index = False, blank = True];
+     optional string subnet_id = 16 [help_text = "Quantum subnet id", max_length = 256, null = True, db_index = False, blank = True];
+     required bool autoconnect = 17 [help_text = "This network can be autoconnected to the slice that owns it", default = True, null = False, db_index = False, blank = True];
+     required manytomany permitted_slices->Slice/Network_permitted_slices:availableNetworks = 18 [db_index = False, null = False, blank = True];
+     required manytomany slices->Slice/NetworkSlice:networks = 19 [db_index = False, null = False, blank = True];
+     required manytomany instances->Instance/Port:networks = 20 [db_index = False, null = False, blank = True];
+}
+
+message Slice (Network){
+     required string name = 1 [max_length = 80, content_type = "stripped", blank = False, help_text = "The Name of the Slice", null = False, db_index = False];
+     required bool enabled = 2 [help_text = "Status for this Slice", default = True, null = False, db_index = False, blank = True];
+     required bool omf_friendly = 3 [default = False, null = False, db_index = False, blank = True];
+     required string description = 4 [help_text = "High level description of the slice and expected activities", max_length = 1024, null = False, db_index = False, blank = True];
+     required string slice_url = 5 [db_index = False, max_length = 512, null = False, content_type = "url", blank = True];
+     required manytoone site->Site:slices = 6 [help_text = "The Site this Slice belongs to", null = False, db_index = True, blank = False];
+     required int32 max_instances = 7 [default = 10, null = False, db_index = False, blank = False];
+     optional manytoone service->Service:slices = 8 [db_index = True, null = True, blank = True];
+     optional string network = 9 [blank = True, max_length = 256, null = True, db_index = False, choices = "((None, 'Default'), ('host', 'Host'), ('bridged', 'Bridged'), ('noauto', 'No Automatic Networks'))"];
+     optional string exposed_ports = 10 [db_index = False, max_length = 256, null = True, blank = True];
+     optional manytoone serviceClass->ServiceClass:slices = 11 [db_index = True, null = True, blank = True];
+     optional manytoone creator->User:slices = 12 [db_index = True, null = True, blank = True];
+     optional manytoone default_flavor->Flavor:slices = 13 [db_index = True, null = True, blank = True];
+     optional manytoone default_image->Image:slices = 14 [db_index = True, null = True, blank = True];
+     optional manytoone default_node->Node:slices = 15 [db_index = True, null = True, blank = True];
+     optional string mount_data_sets = 16 [default = "GenBank", max_length = 256, content_type = "stripped", blank = True, null = True, db_index = False];
+     required string default_isolation = 17 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+     required manytomany tags->Tag = 18 [db_index = False, null = False, blank = True];
+}
+"""
+        args = FakeArgs()
+        args.inputs = proto
+        args.target = xtarget
+        output = XOSGenerator.generate(args)
+        self.assertIn('easter_egg', output)
+
+if __name__ == '__main__':
+    unittest.main()
+
+
diff --git a/lib/xos-genx/xos-genx-tests/helpers.py b/lib/xos-genx/xos-genx-tests/helpers.py
new file mode 100644
index 0000000..232cae1
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/helpers.py
@@ -0,0 +1,36 @@
+
+# Copyright 2017-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 os
+
+# Constants
+OUTPUT_DIR = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/out/")
+
+TMP_TARGET_PATH = os.path.join(OUTPUT_DIR, 'tmp.xtarget')
+
+# Store in this class the args to pass at the generator
+class FakeArgs:
+    pass
+
+class XProtoTestHelpers:
+
+    @staticmethod
+    def write_tmp_target(target):
+        tmp_file = open(TMP_TARGET_PATH, 'w')
+        tmp_file.write(target)
+        tmp_file.close()
+        return TMP_TARGET_PATH
+
diff --git a/lib/xos-genx/xos-genx-tests/optimize_test.py b/lib/xos-genx/xos-genx-tests/optimize_test.py
new file mode 100644
index 0000000..e31deb8
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/optimize_test.py
@@ -0,0 +1,97 @@
+
+# Copyright 2017-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 xosgenx.jinja2_extensions.fol2 import FOL2Python
+
+class XProtoOptimizeTest(unittest.TestCase):
+    def setUp(self):
+        self.f2p = FOL2Python()
+        self.maxDiff=None
+
+    def test_constant(self):
+        input = 'True'
+        output = self.f2p.hoist_outer(input)
+        self.assertEqual(output, input)
+
+    def test_exists(self):
+        input = {'exists': ['X',{'|':['X.foo','y']}]}
+
+        output = self.f2p.hoist_outer(input)
+        expected = {'|': ['y', {'&': [{'not': 'y'}, {'exists': ['X', 'X.foo']}]}]}
+        self.assertEqual(output, expected)
+        
+    def test_exists_implies(self):
+        input = {'exists': ['Foo', {'&': [{'=': ('Foo.a', '1')}, {'->': ['write_access', {'=': ('Foo.b', '1')}]}]}]}
+
+        output = self.f2p.hoist_outer(input)
+        expected = {'|': [{'&': ['write_access', {'exists': ['Foo', {'&': [{'=': ['Foo.a', '1']}, {'=': ['Foo.b', '1']}]}]}]}, {'&': [{'not': 'write_access'}, {'exists': ['Foo', {'=': ['Foo.a', '1']}]}]}]}
+        self.assertEqual(output, expected)
+
+    def test_forall(self):
+        input = {'forall': ['X',{'|':['X.foo','y']}]}
+
+        output = self.f2p.hoist_outer(input)
+        expected = {'|': ['y', {'&': [{'not': 'y'}, {'forall': ['X', 'X.foo']}]}]}
+        self.assertEqual(output, expected)
+
+    def test_exists_embedded(self):
+        input = {'&':['True',{'exists': ['X',{'|':['X.foo','y']}]}]}
+
+        output = self.f2p.hoist_outer(input)
+        expected = {'|': ['y', {'&': [{'not': 'y'}, {'exists': ['X', 'X.foo']}]}]}
+        self.assertEqual(output, expected)
+    
+    def test_exists_equals(self):
+        input = {'&':['True',{'exists': ['X',{'|':['X.foo',{'=':['y','z']}]}]}]}
+
+        output = self.f2p.hoist_outer(input)
+        expected = {'|': [{'=': ['y', 'z']}, {'&': [{'not': {'=': ['y', 'z']}}, {'exists': ['X', 'X.foo']}]}]}
+        self.assertEqual(output, expected)
+
+    def test_exists_nested_constant(self):
+        input = {'&':['True',{'exists': ['X',{'|':['y',{'=':['y','X.foo']}]}]}]}
+
+        output = self.f2p.hoist_outer(input)
+        expected = {'|': ['y', {'&': [{'not': 'y'}, {'exists': ['X', {'=': ['False', 'X.foo']}]}]}]}
+        self.assertEqual(output, expected)
+
+    def test_exists_nested(self):
+        input = {'exists': ['X',{'exists':['Y',{'=':['Y.foo','X.foo']}]}]}
+
+        output = self.f2p.hoist_outer(input)
+        expected = input
+        self.assertEqual(input, output)
+
+    def test_exists_nested2(self):
+        input = {'exists': ['X',{'exists':['Y',{'=':['Z','Y']}]}]}
+
+        output = self.f2p.hoist_outer(input)
+        expected = {'exists': ['Y', {'=': ['Z', 'Y']}]}
+        self.assertEqual(output, expected)
+
+    def test_exists_nested3(self):
+        input = {'exists': ['X',{'exists':['Y',{'=':['Z','X']}]}]}
+
+        output = self.f2p.hoist_outer(input)
+        expected = {'exists': ['X', {'=': ['Z', 'X']}]}
+        self.assertEqual(output, expected)
+
+
+if __name__ == '__main__':
+    unittest.main()
+
+
diff --git a/lib/xos-genx/xos-genx-tests/out/.gitignore b/lib/xos-genx/xos-genx-tests/out/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/out/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/lib/xos-genx/xos-genx-tests/package_test.py b/lib/xos-genx/xos-genx-tests/package_test.py
new file mode 100644
index 0000000..127fc07
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/package_test.py
@@ -0,0 +1,442 @@
+
+# Copyright 2017-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
+import os
+from xosgenx.generator import XOSGenerator
+from helpers import FakeArgs, XProtoTestHelpers
+
+class XProtoPackageTest(unittest.TestCase):
+    def test_package_fqn(self):
+        args = FakeArgs()
+        target = XProtoTestHelpers.write_tmp_target(
+"""
+  {% for m in proto.messages %}
+  {{ m.name }},{{ m.package }},{{ m.fqn }}
+  {% endfor %}
+""")
+
+        xproto =\
+"""
+package xos.core;
+
+message Port (PlCoreBase,ParameterMixin) {
+     required manytoone network->Network:links = 1 [db_index = True, null = False, blank = False];
+     optional manytoone instance->Instance:ports = 2 [db_index = True, null = True, blank = True];
+     optional string ip = 3 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     optional string port_id = 4 [help_text = "Neutron port id", max_length = 256, null = True, db_index = False, blank = True];
+     optional string mac = 5 [help_text = "MAC address associated with this port", max_length = 256, null = True, db_index = False, blank = True];
+     required bool xos_created = 6 [default = False, null = False, db_index = False, blank = True];
+}
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+
+        output = XOSGenerator.generate(args)
+
+        self.assertIn('Port,xos.core,xos.core.Port', output)
+
+    def test_cross_model(self):
+        target = XProtoTestHelpers.write_tmp_target( \
+"""
+  {% for m in proto.messages %}
+  {{ m.fqn }} {
+  {%- for l in m.links %}
+     {%- if proto.message_table[l.peer.fqn] %}
+     {{ l.peer.name }} {
+     {%- set model = proto.message_table[l.peer.fqn] %}
+        {% for f in model.fields %}
+        {{ f.type }} {{ f.name }};
+        {% endfor %}
+     }
+    {%- endif -%}
+    {%- if proto.message_table[m.package + '.' + l.peer.name] %}
+     {{ l.peer.name }} {
+     {%- set model = proto.message_table[m.package + '.' + l.peer.name] %}
+        {% for f in model.fields %}
+        {{ f.type }} {{ f.name }};
+        {% endfor %}
+     }
+     {%- endif -%}
+  {% endfor %}
+  }
+  {% endfor %}
+""")
+
+        xproto = \
+"""
+package xos.network;
+
+message Port (PlCoreBase,ParameterMixin){
+     required manytoone network->Network:links = 1 [db_index = True, null = False, blank = False];
+     optional manytoone instance->xos.core.Instance:ports = 2 [db_index = True, null = True, blank = True];
+     optional string ip = 3 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     optional string port_id = 4 [help_text = "Neutron port id", max_length = 256, null = True, db_index = False, blank = True];
+     optional string mac = 5 [help_text = "MAC address associated with this port", max_length = 256, null = True, db_index = False, blank = True];
+     required bool xos_created = 6 [default = False, null = False, db_index = False, blank = True];
+}
+
+
+package xos.core;
+
+message Instance (PlCoreBase){
+     optional string instance_id = 1 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance id", null = True, db_index = False];
+     optional string instance_uuid = 2 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance uuid", null = True, db_index = False];
+     required string name = 3 [max_length = 200, content_type = "stripped", blank = False, help_text = "Instance name", null = False, db_index = False];
+     optional string instance_name = 4 [max_length = 200, content_type = "stripped", blank = True, help_text = "OpenStack generated name", null = True, db_index = False];
+     optional string ip = 5 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     required manytoone image->Image:instances = 6 [db_index = True, null = False, blank = False];
+     optional manytoone creator->User:instances = 7 [db_index = True, null = True, blank = True];
+     required manytoone slice->Slice:instances = 8 [db_index = True, null = False, blank = False];
+     required manytoone deployment->Deployment:instance_deployment = 9 [db_index = True, null = False, blank = False];
+     required manytoone node->Node:instances = 10 [db_index = True, null = False, blank = False];
+     required int32 numberCores = 11 [help_text = "Number of cores for instance", default = 0, null = False, db_index = False, blank = False];
+     required manytoone flavor->Flavor:instance = 12 [help_text = "Flavor of this instance", default = "get_default_flavor()", null = False, db_index = True, blank = False];
+     optional string userData = 13 [help_text = "user_data passed to instance during creation", null = True, db_index = False, blank = True];
+     required string isolation = 14 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+     optional string volumes = 15 [help_text = "Comma-separated list of directories to expose to parent context", null = True, db_index = False, blank = True];
+     optional manytoone parent->Instance:instance = 16 [help_text = "Parent Instance for containers nested inside of VMs", null = True, db_index = True, blank = True];
+     required manytomany tags->Tag = 17 [db_index = False, null = False, blank = True];
+}
+
+package xos.network;
+
+message Network (PlCoreBase,ParameterMixin) {
+     required string name = 1 [db_index = False, max_length = 32, null = False, blank = False];
+     required manytoone template->NetworkTemplate:network = 2 [db_index = True, null = False, blank = False];
+     required string subnet = 3 [db_index = False, max_length = 32, null = False, blank = True];
+     required string start_ip = 4 [db_index = False, max_length = 32, null = False, blank = True];
+     required string end_ip = 5 [db_index = False, max_length = 32, null = False, blank = True];
+     optional string ports = 6 [db_index = False, max_length = 1024, null = True, blank = True];
+     optional string labels = 7 [db_index = False, max_length = 1024, null = True, blank = True];
+     required manytoone owner->Slice:ownedNetworks = 8 [help_text = "Slice that owns control of this Network", null = False, db_index = True, blank = False];
+     required int32 guaranteed_bandwidth = 9 [default = 0, null = False, db_index = False, blank = False];
+     required bool permit_all_slices = 10 [default = False, null = False, db_index = False, blank = True];
+     optional string topology_parameters = 11 [db_index = False, null = True, blank = True];
+     optional string controller_url = 12 [db_index = False, max_length = 1024, null = True, blank = True];
+     optional string controller_parameters = 13 [db_index = False, null = True, blank = True];
+     optional string network_id = 14 [help_text = "Quantum network", max_length = 256, null = True, db_index = False, blank = True];
+     optional string router_id = 15 [help_text = "Quantum router id", max_length = 256, null = True, db_index = False, blank = True];
+     optional string subnet_id = 16 [help_text = "Quantum subnet id", max_length = 256, null = True, db_index = False, blank = True];
+     required bool autoconnect = 17 [help_text = "This network can be autoconnected to the slice that owns it", default = True, null = False, db_index = False, blank = True];
+     required manytomany permitted_slices->Slice/Network_permitted_slices:availableNetworks = 18 [db_index = False, null = False, blank = True];
+     required manytomany slices->Slice/NetworkSlice:networks = 19 [db_index = False, null = False, blank = True];
+     required manytomany instances->xos.core.Instance/xos.network.Port:networks = 20 [db_index = False, null = False, blank = True];
+}
+
+message Slice (PlCoreBase){
+     required string name = 1 [max_length = 80, content_type = "stripped", blank = False, help_text = "The Name of the Slice", null = False, db_index = False];
+     required bool enabled = 2 [help_text = "Status for this Slice", default = True, null = False, db_index = False, blank = True];
+     required bool omf_friendly = 3 [default = False, null = False, db_index = False, blank = True];
+     required string description = 4 [help_text = "High level description of the slice and expected activities", max_length = 1024, null = False, db_index = False, blank = True];
+     required string slice_url = 5 [db_index = False, max_length = 512, null = False, content_type = "url", blank = True];
+     required manytoone site->Site:slices = 6 [help_text = "The Site this Slice belongs to", null = False, db_index = True, blank = False];
+     required int32 max_instances = 7 [default = 10, null = False, db_index = False, blank = False];
+     optional manytoone service->Service:slices = 8 [db_index = True, null = True, blank = True];
+     optional string network = 9 [blank = True, max_length = 256, null = True, db_index = False, choices = "((None, 'Default'), ('host', 'Host'), ('bridged', 'Bridged'), ('noauto', 'No Automatic Networks'))"];
+     optional string exposed_ports = 10 [db_index = False, max_length = 256, null = True, blank = True];
+     optional manytoone serviceClass->ServiceClass:slices = 11 [db_index = True, null = True, blank = True];
+     optional manytoone creator->User:slices = 12 [db_index = True, null = True, blank = True];
+     optional manytoone default_flavor->Flavor:slices = 13 [db_index = True, null = True, blank = True];
+     optional manytoone default_image->Image:slices = 14 [db_index = True, null = True, blank = True];
+     optional manytoone default_node->Node:slices = 15 [db_index = True, null = True, blank = True];
+     optional string mount_data_sets = 16 [default = "GenBank", max_length = 256, content_type = "stripped", blank = True, null = True, db_index = False];
+     required string default_isolation = 17 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+     required manytomany tags->Tag = 18 [db_index = False, null = False, blank = True];
+}
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+        output = XOSGenerator.generate(args)
+
+        self.assertIn('numberCores', output) # Instance showed up via cross-package call
+        self.assertIn('ip;', output) # Network showed up via cross-package call
+        self.assertIn('max_instances', output) # Slice showed up via implicit in-package call
+
+    def test_base_class_fields(self):
+        target = XProtoTestHelpers.write_tmp_target(
+"""
+  {% for m in proto.messages %}
+  {{ m.name }} {
+  {%- for b in m.bases %}
+     {%- if proto.message_table[b.fqn] -%}
+     {%- set model = proto.message_table[b.fqn] %}
+        {% for f in model.fields %}
+        {{ f.type }} {{ f.name }};
+        {% endfor %}
+     {%- endif -%}
+  {% endfor %}
+  }
+  {% endfor %}
+""")
+
+        xproto =\
+"""
+package xos.network;
+
+message Port (PlCoreBase,ParameterMixin){
+     required manytoone network->Network:links = 1 [db_index = True, null = False, blank = False];
+     optional manytoone instance->Instance:ports = 2 [db_index = True, null = True, blank = True];
+     optional string ip = 3 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     optional string port_id = 4 [help_text = "Neutron port id", max_length = 256, null = True, db_index = False, blank = True];
+     optional string mac = 5 [help_text = "MAC address associated with this port", max_length = 256, null = True, db_index = False, blank = True];
+     required bool xos_created = 6 [default = False, null = False, db_index = False, blank = True];
+}
+
+package xos.someotherpackage;
+
+message Instance (xos.network.Port){
+     optional string instance_id = 1 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance id", null = True, db_index = False];
+     optional string instance_uuid = 2 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance uuid", null = True, db_index = False];
+     required string name = 3 [max_length = 200, content_type = "stripped", blank = False, help_text = "Instance name", null = False, db_index = False];
+     optional string instance_name = 4 [max_length = 200, content_type = "stripped", blank = True, help_text = "OpenStack generated name", null = True, db_index = False];
+     optional string ip = 5 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     required manytoone image->Image:instances = 6 [db_index = True, null = False, blank = False];
+     optional manytoone creator->User:instances = 7 [db_index = True, null = True, blank = True];
+     required manytoone slice->Slice:instances = 8 [db_index = True, null = False, blank = False];
+     required manytoone deployment->Deployment:instance_deployment = 9 [db_index = True, null = False, blank = False];
+     required manytoone node->Node:instances = 10 [db_index = True, null = False, blank = False];
+     required int32 numberCores = 11 [help_text = "Number of cores for instance", default = 0, null = False, db_index = False, blank = False];
+     required manytoone flavor->Flavor:instance = 12 [help_text = "Flavor of this instance", default = "get_default_flavor()", null = False, db_index = True, blank = False];
+     optional string userData = 13 [help_text = "user_data passed to instance during creation", null = True, db_index = False, blank = True];
+     required string isolation = 14 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+     optional string volumes = 15 [help_text = "Comma-separated list of directories to expose to parent context", null = True, db_index = False, blank = True];
+     optional manytoone parent->Instance:instance = 16 [help_text = "Parent Instance for containers nested inside of VMs", null = True, db_index = True, blank = True];
+     required manytomany tags->Tag = 17 [db_index = False, null = False, blank = True];
+}
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+        output = XOSGenerator.generate(args)
+
+        self.assertIn('xos_created', output)
+
+    def test_from_base(self):
+        target = XProtoTestHelpers.write_tmp_target( \
+"""
+  {% for f in xproto_base_fields(proto.messages.3, proto.message_table) %}
+        {{ f.type }} {{ f.name }};
+  {% endfor %}
+""")
+
+        xproto =\
+"""
+option app_name = "firstapp";
+
+message Port (PlCoreBase,ParameterMixin){
+     required string easter_egg = 1;
+     required manytoone network->Network:links = 1 [db_index = True, null = False, blank = False];
+     optional manytoone instance->Instance:ports = 2 [db_index = True, null = True, blank = True];
+     optional string ip = 3 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     optional string port_id = 4 [help_text = "Neutron port id", max_length = 256, null = True, db_index = False, blank = True];
+     optional string mac = 5 [help_text = "MAC address associated with this port", max_length = 256, null = True, db_index = False, blank = True];
+     required bool xos_created = 6 [default = False, null = False, db_index = False, blank = True];
+}
+
+package A;
+
+message Instance (Port){
+     optional string instance_id = 1 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance id", null = True, db_index = False];
+     optional string instance_uuid = 2 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance uuid", null = True, db_index = False];
+     required string name = 3 [max_length = 200, content_type = "stripped", blank = False, help_text = "Instance name", null = False, db_index = False];
+     optional string instance_name = 4 [max_length = 200, content_type = "stripped", blank = True, help_text = "OpenStack generated name", null = True, db_index = False];
+     optional string ip = 5 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     required manytoone image->Image:instances = 6 [db_index = True, null = False, blank = False];
+     optional manytoone creator->User:instances = 7 [db_index = True, null = True, blank = True];
+     required manytoone slice->Slice:instances = 8 [db_index = True, null = False, blank = False];
+     required manytoone deployment->Deployment:instance_deployment = 9 [db_index = True, null = False, blank = False];
+     required manytoone node->Node:instances = 10 [db_index = True, null = False, blank = False];
+     required int32 numberCores = 11 [help_text = "Number of cores for instance", default = 0, null = False, db_index = False, blank = False];
+     required manytoone flavor->Flavor:instance = 12 [help_text = "Flavor of this instance", default = "get_default_flavor()", null = False, db_index = True, blank = False];
+     optional string userData = 13 [help_text = "user_data passed to instance during creation", null = True, db_index = False, blank = True];
+     required string isolation = 14 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+     optional string volumes = 15 [help_text = "Comma-separated list of directories to expose to parent context", null = True, db_index = False, blank = True];
+     optional manytoone parent->Instance:instance = 16 [help_text = "Parent Instance for containers nested inside of VMs", null = True, db_index = True, blank = True];
+     required manytomany tags->Tag = 17 [db_index = False, null = False, blank = True];
+}
+
+package B;
+
+option app_name="networkapp";
+
+message Network (A.Instance) {
+     required string name = 1 [db_index = False, max_length = 32, null = False, blank = False];
+     required manytoone template->NetworkTemplate:network = 2 [db_index = True, null = False, blank = False];
+     required string subnet = 3 [db_index = False, max_length = 32, null = False, blank = True];
+     required string start_ip = 4 [db_index = False, max_length = 32, null = False, blank = True];
+     required string end_ip = 5 [db_index = False, max_length = 32, null = False, blank = True];
+     optional string ports = 6 [db_index = False, max_length = 1024, null = True, blank = True];
+     optional string labels = 7 [db_index = False, max_length = 1024, null = True, blank = True];
+     required manytoone owner->Slice:ownedNetworks = 8 [help_text = "Slice that owns control of this Network", null = False, db_index = True, blank = False];
+     required int32 guaranteed_bandwidth = 9 [default = 0, null = False, db_index = False, blank = False];
+     required bool permit_all_slices = 10 [default = False, null = False, db_index = False, blank = True];
+     optional string topology_parameters = 11 [db_index = False, null = True, blank = True];
+     optional string controller_url = 12 [db_index = False, max_length = 1024, null = True, blank = True];
+     optional string controller_parameters = 13 [db_index = False, null = True, blank = True];
+     optional string network_id = 14 [help_text = "Quantum network", max_length = 256, null = True, db_index = False, blank = True];
+     optional string router_id = 15 [help_text = "Quantum router id", max_length = 256, null = True, db_index = False, blank = True];
+     optional string subnet_id = 16 [help_text = "Quantum subnet id", max_length = 256, null = True, db_index = False, blank = True];
+     required bool autoconnect = 17 [help_text = "This network can be autoconnected to the slice that owns it", default = True, null = False, db_index = False, blank = True];
+     required manytomany permitted_slices->Slice/Network_permitted_slices:availableNetworks = 18 [db_index = False, null = False, blank = True];
+     required manytomany slices->Slice/NetworkSlice:networks = 19 [db_index = False, null = False, blank = True];
+     required manytomany instances->Instance/Port:networks = 20 [db_index = False, null = False, blank = True];
+}
+
+option app_name="sliceapp";
+
+message Slice (Network){
+     required string name = 1 [max_length = 80, content_type = "stripped", blank = False, help_text = "The Name of the Slice", null = False, db_index = False];
+     required bool enabled = 2 [help_text = "Status for this Slice", default = True, null = False, db_index = False, blank = True];
+     required bool omf_friendly = 3 [default = False, null = False, db_index = False, blank = True];
+     required string description = 4 [help_text = "High level description of the slice and expected activities", max_length = 1024, null = False, db_index = False, blank = True];
+     required string slice_url = 5 [db_index = False, max_length = 512, null = False, content_type = "url", blank = True];
+     required manytoone site->Site:slices = 6 [help_text = "The Site this Slice belongs to", null = False, db_index = True, blank = False];
+     required int32 max_instances = 7 [default = 10, null = False, db_index = False, blank = False];
+     optional manytoone service->Service:slices = 8 [db_index = True, null = True, blank = True];
+     optional string network = 9 [blank = True, max_length = 256, null = True, db_index = False, choices = "((None, 'Default'), ('host', 'Host'), ('bridged', 'Bridged'), ('noauto', 'No Automatic Networks'))"];
+     optional string exposed_ports = 10 [db_index = False, max_length = 256, null = True, blank = True];
+     optional manytoone serviceClass->ServiceClass:slices = 11 [db_index = True, null = True, blank = True];
+     optional manytoone creator->User:slices = 12 [db_index = True, null = True, blank = True];
+     optional manytoone default_flavor->Flavor:slices = 13 [db_index = True, null = True, blank = True];
+     optional manytoone default_image->Image:slices = 14 [db_index = True, null = True, blank = True];
+     optional manytoone default_node->Node:slices = 15 [db_index = True, null = True, blank = True];
+     optional string mount_data_sets = 16 [default = "GenBank", max_length = 256, content_type = "stripped", blank = True, null = True, db_index = False];
+     required string default_isolation = 17 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+     required manytomany tags->Tag = 18 [db_index = False, null = False, blank = True];
+}
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+        output = XOSGenerator.generate(args)
+
+        self.assertIn('easter_egg', output)
+
+    def test_model_options(self):
+        target = XProtoTestHelpers.write_tmp_target(
+"""
+  Options:
+
+  {{ proto.options }}
+  {% for m in proto.messages %}
+        {{ m.options.app_name }}
+  {% endfor %}
+""")
+
+        xproto =\
+"""
+option app_name = "firstapp";
+
+message Port (PlCoreBase,ParameterMixin){
+     required string easter_egg = 1;
+     required manytoone network->Network:links = 1 [db_index = True, null = False, blank = False];
+     optional manytoone instance->Instance:ports = 2 [db_index = True, null = True, blank = True];
+     optional string ip = 3 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     optional string port_id = 4 [help_text = "Neutron port id", max_length = 256, null = True, db_index = False, blank = True];
+     optional string mac = 5 [help_text = "MAC address associated with this port", max_length = 256, null = True, db_index = False, blank = True];
+     required bool xos_created = 6 [default = False, null = False, db_index = False, blank = True];
+}
+
+package A;
+
+message Instance (Port){
+     optional string instance_id = 1 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance id", null = True, db_index = False];
+     optional string instance_uuid = 2 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance uuid", null = True, db_index = False];
+     required string name = 3 [max_length = 200, content_type = "stripped", blank = False, help_text = "Instance name", null = False, db_index = False];
+     optional string instance_name = 4 [max_length = 200, content_type = "stripped", blank = True, help_text = "OpenStack generated name", null = True, db_index = False];
+     optional string ip = 5 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     required manytoone image->Image:instances = 6 [db_index = True, null = False, blank = False];
+     optional manytoone creator->User:instances = 7 [db_index = True, null = True, blank = True];
+     required manytoone slice->Slice:instances = 8 [db_index = True, null = False, blank = False];
+     required manytoone deployment->Deployment:instance_deployment = 9 [db_index = True, null = False, blank = False];
+     required manytoone node->Node:instances = 10 [db_index = True, null = False, blank = False];
+     required int32 numberCores = 11 [help_text = "Number of cores for instance", default = 0, null = False, db_index = False, blank = False];
+     required manytoone flavor->Flavor:instance = 12 [help_text = "Flavor of this instance", default = "get_default_flavor()", null = False, db_index = True, blank = False];
+     optional string userData = 13 [help_text = "user_data passed to instance during creation", null = True, db_index = False, blank = True];
+     required string isolation = 14 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+     optional string volumes = 15 [help_text = "Comma-separated list of directories to expose to parent context", null = True, db_index = False, blank = True];
+     optional manytoone parent->Instance:instance = 16 [help_text = "Parent Instance for containers nested inside of VMs", null = True, db_index = True, blank = True];
+     required manytomany tags->Tag = 17 [db_index = False, null = False, blank = True];
+}
+
+package B;
+
+option app_name = "networkapp";
+
+message Network (A.Instance) {
+     required string name = 1 [db_index = False, max_length = 32, null = False, blank = False];
+     required manytoone template->NetworkTemplate:network = 2 [db_index = True, null = False, blank = False];
+     required string subnet = 3 [db_index = False, max_length = 32, null = False, blank = True];
+     required string start_ip = 4 [db_index = False, max_length = 32, null = False, blank = True];
+     required string end_ip = 5 [db_index = False, max_length = 32, null = False, blank = True];
+     optional string ports = 6 [db_index = False, max_length = 1024, null = True, blank = True];
+     optional string labels = 7 [db_index = False, max_length = 1024, null = True, blank = True];
+     required manytoone owner->Slice:ownedNetworks = 8 [help_text = "Slice that owns control of this Network", null = False, db_index = True, blank = False];
+     required int32 guaranteed_bandwidth = 9 [default = 0, null = False, db_index = False, blank = False];
+     required bool permit_all_slices = 10 [default = False, null = False, db_index = False, blank = True];
+     optional string topology_parameters = 11 [db_index = False, null = True, blank = True];
+     optional string controller_url = 12 [db_index = False, max_length = 1024, null = True, blank = True];
+     optional string controller_parameters = 13 [db_index = False, null = True, blank = True];
+     optional string network_id = 14 [help_text = "Quantum network", max_length = 256, null = True, db_index = False, blank = True];
+     optional string router_id = 15 [help_text = "Quantum router id", max_length = 256, null = True, db_index = False, blank = True];
+     optional string subnet_id = 16 [help_text = "Quantum subnet id", max_length = 256, null = True, db_index = False, blank = True];
+     required bool autoconnect = 17 [help_text = "This network can be autoconnected to the slice that owns it", default = True, null = False, db_index = False, blank = True];
+     required manytomany permitted_slices->Slice/Network_permitted_slices:availableNetworks = 18 [db_index = False, null = False, blank = True];
+     required manytomany slices->Slice/NetworkSlice:networks = 19 [db_index = False, null = False, blank = True];
+     required manytomany instances->Instance/Port:networks = 20 [db_index = False, null = False, blank = True];
+}
+
+
+option app_name = "networkapp";
+
+message Slice (Network){
+     required string name = 1 [max_length = 80, content_type = "stripped", blank = False, help_text = "The Name of the Slice", null = False, db_index = False];
+     required bool enabled = 2 [help_text = "Status for this Slice", default = True, null = False, db_index = False, blank = True];
+     required bool omf_friendly = 3 [default = False, null = False, db_index = False, blank = True];
+     required string description = 4 [help_text = "High level description of the slice and expected activities", max_length = 1024, null = False, db_index = False, blank = True];
+     required string slice_url = 5 [db_index = False, max_length = 512, null = False, content_type = "url", blank = True];
+     required manytoone site->Site:slices = 6 [help_text = "The Site this Slice belongs to", null = False, db_index = True, blank = False];
+     required int32 max_instances = 7 [default = 10, null = False, db_index = False, blank = False];
+     optional manytoone service->Service:slices = 8 [db_index = True, null = True, blank = True];
+     optional string network = 9 [blank = True, max_length = 256, null = True, db_index = False, choices = "((None, 'Default'), ('host', 'Host'), ('bridged', 'Bridged'), ('noauto', 'No Automatic Networks'))"];
+     optional string exposed_ports = 10 [db_index = False, max_length = 256, null = True, blank = True];
+     optional manytoone serviceClass->ServiceClass:slices = 11 [db_index = True, null = True, blank = True];
+     optional manytoone creator->User:slices = 12 [db_index = True, null = True, blank = True];
+     optional manytoone default_flavor->Flavor:slices = 13 [db_index = True, null = True, blank = True];
+     optional manytoone default_image->Image:slices = 14 [db_index = True, null = True, blank = True];
+     optional manytoone default_node->Node:slices = 15 [db_index = True, null = True, blank = True];
+     optional string mount_data_sets = 16 [default = "GenBank", max_length = 256, content_type = "stripped", blank = True, null = True, db_index = False];
+     required string default_isolation = 17 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+     required manytomany tags->Tag = 18 [db_index = False, null = False, blank = True];
+}
+"""
+         
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+        output = XOSGenerator.generate(args)
+
+        self.assertEqual(output.count('firstapp'), 2)
+        self.assertEqual(output.count('networkapp'), 2)
+
+
+if __name__ == '__main__':
+    unittest.main()
+
+
diff --git a/lib/xos-genx/xos-genx-tests/parse_test.py b/lib/xos-genx/xos-genx-tests/parse_test.py
new file mode 100644
index 0000000..88c7372
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/parse_test.py
@@ -0,0 +1,130 @@
+
+# Copyright 2017-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 xosgenx.generator import XOSGenerator
+from helpers import FakeArgs, XProtoTestHelpers
+
+class XProtoParseTests(unittest.TestCase):
+    def test_global_options(self):
+
+        xtarget = XProtoTestHelpers.write_tmp_target("{{ options }}")
+
+        xproto = \
+"""
+    option kind = "vsg";
+    option verbose_name = "vSG Service";
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = xtarget
+        output = XOSGenerator.generate(args)
+        self.assertIn("vsg", output)
+        self.assertIn("vSG Service", output)
+
+    def test_basic_proto(self):
+        xtarget = XProtoTestHelpers.write_tmp_target("{{ proto }}")
+
+        xproto = \
+"""
+message Person {
+  required string name = 1;
+  required int32 id = 2;  // Unique ID number for this person.
+  optional string email = 3 [symphony = "da da da dum"];
+
+  enum PhoneType {
+    MOBILE = 0;
+    HOME = 1;
+    WORK = 2;
+  }
+
+  required  string number = 1;
+  optional PhoneType type = 2;
+
+  repeated PhoneNumber phones = 4;
+}
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = xtarget
+        output = XOSGenerator.generate(args)
+        self.assertIn("PhoneNumber", output)
+
+    def test_link_extensions(self):
+
+        xtarget = XProtoTestHelpers.write_tmp_target("{{ proto.messages.0.links }}")
+        xproto = \
+"""
+message links {
+    required manytoone vrouter_service->VRouterService:device_ports = 4 [db_index = True, null = False, blank = False];
+}
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = xtarget
+        output = XOSGenerator.generate(args)
+        self.assertIn("VRouterService", output)
+	
+	pass
+
+    def test_through_extensions(self):
+        xtarget = XProtoTestHelpers.write_tmp_target("{{ proto.messages.0.links.0.through }}")
+        xproto = \
+"""
+message links {
+    required manytomany vrouter_service->VRouterService/ServiceProxy:device_ports = 4 [db_index = True, null = False, blank = False];
+}
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = xtarget
+        output = XOSGenerator.generate(args)
+        self.assertIn("ServiceProxy", output)
+
+    def test_message_options(self):
+        xtarget = XProtoTestHelpers.write_tmp_target("{{ proto.messages.0.options.type }}")
+        xproto = \
+"""
+message link {
+    option type = "e1000";
+}
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = xtarget
+        output = XOSGenerator.generate(args)
+        self.assertIn("e1000", output)
+
+	pass
+
+    def test_message_base(self):
+        xtarget = XProtoTestHelpers.write_tmp_target("{{ proto.messages.0.bases }}")
+        xproto = \
+"""
+message base(Base) {
+}
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = xtarget
+        output = XOSGenerator.generate(args)
+        self.assertIn("Base", output)
+
+if __name__ == '__main__':
+    unittest.main()
+
+
diff --git a/lib/xos-genx/xos-genx-tests/policy_test.py b/lib/xos-genx/xos-genx-tests/policy_test.py
new file mode 100644
index 0000000..3ff700b
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/policy_test.py
@@ -0,0 +1,291 @@
+
+# Copyright 2017-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 xosgenx.generator import XOSGenerator
+from helpers import FakeArgs, XProtoTestHelpers
+import pdb
+
+"""
+The tests below convert the policy logic expression
+into Python, set up an appropriate environment and execute the Python.
+"""
+
+class XProtoPolicyTest(unittest.TestCase):
+    def test_annotation(self):
+        xproto = \
+"""
+    policy true_policy < True >
+
+    message always::true_policy {
+        required int still = 9;
+    }
+"""
+
+        target = XProtoTestHelpers.write_tmp_target("{{ proto.messages.0 }}")
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+
+        output = XOSGenerator.generate(args)
+        self.assertIn("true_policy", output)
+
+    def test_constant(self):
+        xproto = \
+"""
+    policy true_policy < True >
+"""
+
+        target = XProtoTestHelpers.write_tmp_target("{{ proto.policies.true_policy }}")
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+
+        output = XOSGenerator.generate(args).replace('t','T')
+        self.assertTrue(eval(output)) 
+
+    def test_function_term(self):
+        xproto = \
+"""
+    policy slice_user < slice.user.compute_is_admin() >
+"""
+
+        target = XProtoTestHelpers.write_tmp_target("{{ proto.policies.slice_user }}")
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+
+        output = XOSGenerator.generate(args)
+       
+        slice = FakeArgs()
+        slice.user = FakeArgs()
+        slice.user.compute_is_admin = lambda: True
+
+        expr = eval(output)
+        self.assertTrue(expr)
+
+    def test_term(self):
+        xproto = \
+"""
+    policy slice_user < slice.user.is_admin >
+"""
+
+        target = XProtoTestHelpers.write_tmp_target("{{ proto.policies.slice_user }}")
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+
+        output = XOSGenerator.generate(args)
+       
+        slice = FakeArgs()
+        slice.user = FakeArgs()
+        slice.user.is_admin = True
+
+        expr = eval(output)
+        self.assertTrue(expr)
+
+    def test_num_constant(self):
+        xproto = \
+"""
+    policy slice_user < slice.user.age = 57 >
+"""
+
+        target = XProtoTestHelpers.write_tmp_target("{{ proto.policies.slice_user }}")
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+
+        output = XOSGenerator.generate(args)
+       
+        slice = FakeArgs()
+        slice.user = FakeArgs()
+        slice.user.is_admin = True
+
+        expr = eval(output)
+        self.assertTrue(expr)
+
+    def test_string_constant(self):
+        xproto = \
+"""
+    policy slice_user < slice.user.email = "admin@opencord.org" >
+"""
+
+        target = XProtoTestHelpers.write_tmp_target("{{ proto.policies.slice_user }}")
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+
+        output = XOSGenerator.generate(args)
+       
+        slice = FakeArgs()
+        slice.user = FakeArgs()
+        slice.user.is_admin = True
+
+        expr = eval(output)
+        self.assertTrue(expr)
+
+    def test_equal(self):
+        xproto = \
+"""
+    policy slice_user < slice.user = obj.user >
+"""
+
+        target = XProtoTestHelpers.write_tmp_target("{{ proto.policies.slice_user }}")
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+
+        output = XOSGenerator.generate(args)
+       
+        slice = FakeArgs()
+        slice.user = 'twin'
+        obj = FakeArgs()
+        obj.user = 'twin'
+
+        (op, operands), = eval(output).items()
+        expr = op.join(operands).replace('=','==')
+
+        self.assertTrue(eval(expr))
+
+    def test_bin(self):
+        xproto = \
+"""
+    policy slice_admin < slice.is_admin | obj.empty >
+"""
+        target = XProtoTestHelpers.write_tmp_target("{{ proto.policies.slice_admin }}")
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+
+        output = XOSGenerator.generate(args)
+
+        slice = FakeArgs()
+        slice.is_admin = False
+        obj = FakeArgs()
+        obj.empty = []
+
+        (op, operands), = eval(output).items()
+        expr = op.join(operands).replace('|',' or ')
+
+        self.assertFalse(eval(expr))
+
+    def test_implies(self):
+        xproto = \
+"""
+    policy implies < obj.name -> obj.creator >
+"""
+        target = XProtoTestHelpers.write_tmp_target("{{ proto.policies.implies }}")
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+
+        output = XOSGenerator.generate(args)
+
+        slice = FakeArgs()
+        slice.is_admin = False
+        obj = FakeArgs()
+        obj.name = 'Thing 1'
+        obj.creator = None
+
+        (op, operands), = eval(output).items()
+        expr = 'not ' + op.join(operands).replace('->',' or ')
+
+        self.assertFalse(eval(expr))
+   
+    def test_exists(self):
+        xproto = \
+"""
+    policy privilege < exists Privilege: Privilege.object_id = obj.id >
+"""
+
+        target = XProtoTestHelpers.write_tmp_target("{{ proto.policies.privilege }} ")
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+
+        output = XOSGenerator.generate(args)
+        
+        Privilege = FakeArgs()
+        Privilege.object_id = 1
+        obj = FakeArgs()
+        obj.id = 1
+
+        (op, operands), = eval(output).items()
+        (op2, operands2), = operands[1].items()
+        expr = op2.join(operands2).replace('=','==')
+
+        self.assertTrue(eval(expr))
+
+    def test_policy_function(self):
+        xproto = \
+"""
+    policy slice_policy < exists Privilege: Privilege.object_id = obj.id >
+    policy network_slice_policy < *slice_policy(slice) >
+"""
+
+        target = XProtoTestHelpers.write_tmp_target("{{ proto.policies.network_slice_policy }} ")
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+
+        output = XOSGenerator.generate(args)
+        
+        (op, operands), = eval(output).items()
+
+        self.assertIn('slice_policy', operands)
+        self.assertIn('slice', operands)
+
+    def test_policy_missing_function(self):
+        xproto = \
+"""
+    policy slice_policy < exists Privilege: Privilege.object_id = obj.id >
+    policy network_slice_policy < *slice_policyX(slice) >
+"""
+
+        target = XProtoTestHelpers.write_tmp_target("{{ proto.policies.network_slice_policy }} ")
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+
+        with self.assertRaises(Exception):
+            output = XOSGenerator.generate(args)
+        
+
+    def test_forall(self):
+        # This one we only parse
+        xproto = \
+"""
+    policy instance < forall Instance: exists Credential: Credential.obj_id = Instance.obj_id >
+"""
+
+        target = XProtoTestHelpers.write_tmp_target("{{ proto.policies.instance }}")
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+
+        output = XOSGenerator.generate(args)
+        (op, operands), = eval(output).items()
+
+        self.assertEqual(op,'forall')
+
+
+if __name__ == '__main__':
+    unittest.main()
+
+
diff --git a/lib/xos-genx/xos-genx-tests/pure_proto_test.py b/lib/xos-genx/xos-genx-tests/pure_proto_test.py
new file mode 100644
index 0000000..511682e
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/pure_proto_test.py
@@ -0,0 +1,133 @@
+
+# Copyright 2017-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 xosgenx.generator import XOSGenerator
+from helpers import FakeArgs, XProtoTestHelpers
+
+# Generate from xproto, then generate from equivalent proto
+class XPureProtobufGenerator(unittest.TestCase):
+    def test_pure_proto(self):
+		xproto = \
+"""
+message VRouterPort (XOSBase){
+     optional string name = 1 [help_text = "port friendly name", max_length = 20, null = True, db_index = False, blank = True];
+     required string openflow_id = 2 [help_text = "port identifier in ONOS", max_length = 21, null = False, db_index = False, blank = False];
+     required manytoone vrouter_device->VRouterDevice:ports = 3 [db_index = True, null = False, blank = False];
+     required manytoone vrouter_service->VRouterService:device_ports = 4 [db_index = True, null = False, blank = False];
+}
+"""
+
+		proto = \
+"""
+message VRouterPort {
+  option bases = "XOSBase";
+  optional string name = 1 [ null = "True",  max_length = "20",  blank = "True",  help_text = "port friendly name",  modifier = "optional",  db_index = "False" ];
+  required string openflow_id = 2 [ null = "False",  max_length = "21",  blank = "False",  help_text = "port identifier in ONOS",  modifier = "required",  db_index = "False" ];
+  required int32 vrouter_device = 3 [ null = "False",  blank = "False",  model = "VRouterDevice",  modifier = "required",  type = "link",  port = "ports",  db_index = "True", link = "manytoone"];
+  required int32 vrouter_service = 4 [ null = "False",  blank = "False",  model = "VRouterService",  modifier = "required",  type = "link",  port = "device_ports",  db_index = "True", link = "manytoone"];
+}
+"""
+		target = XProtoTestHelpers.write_tmp_target(
+"""
+from header import *
+{% for m in proto.messages %}
+{% if file_exists(xproto_base_name(m.name)|lower+'_header.py') -%}from {{xproto_base_name(m.name)|lower }}_header import *{% endif %}
+{% if file_exists(xproto_base_name(m.name)|lower+'_top.py') -%}{{ include_file(xproto_base_name(m.name)|lower+'_top.py') }} {% endif %}
+
+{%- for l in m.links %}
+
+{% if l.peer.name != m.name %}
+from core.models.{{ l.peer.name | lower }} import {{ l.peer.name }}
+{% endif %}
+
+{%- endfor %}
+{% for b in m.bases %}
+{% if b!='XOSBase' and 'Mixin' not in b%}
+from core.models.{{b.name | lower}} import {{ b.name }}
+{% endif %}
+{% endfor %}
+
+
+class {{ m.name }}{{ xproto_base_def(m, m.bases) }}:
+  # Primitive Fields (Not Relations)
+  {% for f in m.fields %}
+  {%- if not f.link -%}
+  {{ f.name }} = {{ xproto_django_type(f.type, f.options) }}( {{ xproto_django_options_str(f) }} )
+  {% endif %}
+  {%- endfor %}
+
+  # Relations
+  {% for l in m.links %}
+  {{ l.src_port }} = {{ xproto_django_link_type(l) }}( {%- if l.peer.name==m.name -%}'self'{%- else -%}{{ l.peer.name }} {%- endif -%}, {{ xproto_django_link_options_str(l, l.dst_port ) }} )
+  {%- endfor %}
+
+  {% if file_exists(m.name|lower + '_model.py') -%}{{ include_file(m.name|lower + '_model.py') | indent(width=2)}}{%- endif %}
+  pass
+
+{% if file_exists(xproto_base_name(m.name)|lower+'_bottom.py') -%}{{ include_file(xproto_base_name(m.name)|lower+'_bottom.py') }}{% endif %}
+{% endfor %}
+""")
+
+		args_xproto = FakeArgs()
+		args_xproto.inputs = xproto
+		args_xproto.target = target
+		xproto_gen = XOSGenerator.generate(args_xproto)
+
+		count1 = len(xproto_gen.split('\n'))
+
+		args_proto = FakeArgs()
+		args_proto.inputs = proto
+		args_proto.target = target
+		args_proto.rev = True
+		proto_gen = XOSGenerator.generate(args_proto)
+		count2 = len(proto_gen.split('\n'))
+
+		self.assertEqual(count1, count2)
+
+    def test_pure_policies(self):
+		xproto = \
+"""
+policy my_policy < exists x:a=b >
+"""
+
+		proto = \
+"""
+option my_policy = "policy:< exists x:a=b >";
+"""
+		target = XProtoTestHelpers.write_tmp_target(
+"""
+{{ policies }}
+""")
+
+		args_xproto = FakeArgs()
+		args_xproto.inputs = xproto
+		args_xproto.target = target
+		xproto_gen = XOSGenerator.generate(args_xproto)
+
+		args_proto = FakeArgs()
+		args_proto.inputs = proto
+		args_proto.target = target
+		args_proto.rev = True
+		proto_gen = XOSGenerator.generate(args_proto)
+
+		self.assertEqual(proto_gen, xproto_gen)
+
+if __name__ == '__main__':
+    unittest.main()
+
+
diff --git a/lib/xos-genx/xos-genx-tests/rlinks_test.py b/lib/xos-genx/xos-genx-tests/rlinks_test.py
new file mode 100644
index 0000000..b195249
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/rlinks_test.py
@@ -0,0 +1,66 @@
+
+# Copyright 2017-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 xosgenx.generator import XOSGenerator
+from helpers import FakeArgs, XProtoTestHelpers
+
+class XProtoRlinkTests(unittest.TestCase):
+    def test_proto_generator(self):
+        target = XProtoTestHelpers.write_tmp_target("""
+{% for m in proto.messages %}
+   {% for r in m.rlinks %}
+       {{ r }}
+   {% endfor %}
+{% endfor %}
+""")
+
+        xproto = \
+"""
+message VRouterPort (PlCoreBase){
+     optional string name = 1 [help_text = "port friendly name", max_length = 20, null = True, db_index = False, blank = True];
+     required string openflow_id = 2 [help_text = "port identifier in ONOS", max_length = 21, null = False, db_index = False, blank = False];
+     required manytoone vrouter_device->VRouterDevice:ports = 3 [db_index = True, null = False, blank = False];
+     required manytoone vrouter_service->VRouterService:device_ports = 4 [db_index = True, null = False, blank = False];
+}
+
+message VRouterService (Service) {
+     optional string rest_hostname = 1 [db_index = False, max_length = 255, null = True, content_type = "stripped", blank = True];
+     required int32 rest_port = 2 [default = 8181, null = False, db_index = False, blank = False];
+     required string rest_user = 3 [default = "onos", max_length = 255, content_type = "stripped", blank = False, null = False, db_index = False];
+     required string rest_pass = 4 [default = "rocks", max_length = 255, content_type = "stripped", blank = False, null = False, db_index = False];
+}
+
+message VRouterDevice (PlCoreBase){
+     optional string name = 1 [help_text = "device friendly name", max_length = 20, null = True, db_index = False, blank = True];
+     required string openflow_id = 2 [help_text = "device identifier in ONOS", max_length = 20, null = False, db_index = False, blank = False];
+     required string config_key = 3 [default = "basic", max_length = 32, blank = False, help_text = "configuration key", null = False, db_index = False];
+     required string driver = 4 [help_text = "driver type", max_length = 32, null = False, db_index = False, blank = False];
+     required manytoone vrouter_service->VRouterService:devices = 5 [db_index = True, null = False, blank = False];
+}
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = target
+        output = XOSGenerator.generate(args)
+        self.assertIn("'src_port': 'device_ports'", output)
+        self.assertIn("'src_port': 'ports'", output)
+
+if __name__ == '__main__':
+    unittest.main()
+
+
diff --git a/lib/xos-genx/xos-genx-tests/swagger_test.py b/lib/xos-genx/xos-genx-tests/swagger_test.py
new file mode 100644
index 0000000..f87f47a
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/swagger_test.py
@@ -0,0 +1,72 @@
+
+# Copyright 2017-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
+
+import yaml
+from xosgenx.generator import XOSGenerator
+from helpers import FakeArgs, OUTPUT_DIR
+
+class Args:
+    pass
+
+class XOSGeneratorTest(unittest.TestCase):
+
+    def test_swagger_target(self):
+        """
+        [XOS-GenX] The swagger xtarget should generate the appropriate json
+        """
+
+        # xosgenx --output . --target xosgenx/targets/swagger.xtarget --write-to-file single  --dest-file swagger.yaml ../../xos/core/models/core.xproto
+        # http-server --cors Users/teone/Sites/opencord/orchestration/xos/lib/xos-genx/
+        xproto = \
+            """
+            option app_label = "core";
+    
+            message Instance::instance_policy (XOSBase) {
+                 option validators = "instance_creator:Instance has no creator, instance_isolation: Container instance {obj.name} must use container image, instance_isolation_container_vm_parent:Container-vm instance {obj.name} must have a parent, instance_parent_isolation_container_vm:Parent field can only be set on Container-vm instances ({obj.name}), instance_isolation_vm: VM Instance {obj.name} must use VM image, instance_creator_privilege: instance creator has no privileges on slice";
+                 optional string instance_id = 1 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance id", null = True, db_index = False];
+                 optional string instance_uuid = 2 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance uuid", null = True, db_index = False];
+                 required string name = 3 [max_length = 200, content_type = "stripped", blank = False, help_text = "Instance name", null = False, db_index = False];
+                 optional string instance_name = 4 [max_length = 200, content_type = "stripped", blank = True, help_text = "OpenStack generated name", null = True, db_index = False];
+                 optional string ip = 5 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False, gui_hidden = True];
+                 required manytoone image->Image:instances = 6 [db_index = True, null = False, blank = False];
+                 optional manytoone creator->User:instances = 7 [db_index = True, null = True, blank = True];
+                 required manytoone slice->Slice:instances = 8 [db_index = True, null = False, blank = False];
+                 required manytoone deployment->Deployment:instance_deployment = 9 [db_index = True, null = False, blank = False];
+                 required manytoone node->Node:instances = 10 [db_index = True, null = False, blank = False];
+                 required int32 numberCores = 11 [help_text = "Number of cores for instance", default = 0, null = False, db_index = False, blank = False];
+                 required manytoone flavor->Flavor:instance = 12 [help_text = "Flavor of this instance", null = False, db_index = True, blank = False];
+                 optional string userData = 13 [help_text = "user_data passed to instance during creation", null = True, db_index = False, blank = True, varchar = True];
+                 required string isolation = 14 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+                 optional string volumes = 15 [help_text = "Comma-separated list of directories to expose to parent context", null = True, db_index = False, blank = True];
+                 optional manytoone parent->Instance:instance = 16 [help_text = "Parent Instance for containers nested inside of VMs", null = True, db_index = True, blank = True];
+            }
+            """
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = 'swagger.xtarget'
+        args.output = OUTPUT_DIR
+        args.write_to_file = "single"
+        args.dest_file = "swagger.yaml"
+        args.quiet = False
+        output = XOSGenerator.generate(args)
+        self.assertIn("/xosapi/v1/core/instances/:", output)
+        self.assertIn("/xosapi/v1/core/instances/{id}:", output)
+        self.assertIn("Instance:", output)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/lib/xos-genx/xos-genx-tests/target_test.py b/lib/xos-genx/xos-genx-tests/target_test.py
new file mode 100644
index 0000000..b45f5ed
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/target_test.py
@@ -0,0 +1,129 @@
+
+# Copyright 2017-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
+import os
+from xosgenx.generator import XOSGenerator
+from helpers import FakeArgs, XProtoTestHelpers, OUTPUT_DIR
+
+TEST_FILE = "test_file"
+
+TEST_OUTPUT = "Do re mi fa so la ti do"
+
+class XProtoTargetTests(unittest.TestCase):
+
+    def setUp(self):
+        test_file = open(os.path.join(OUTPUT_DIR, TEST_FILE), 'w')
+        test_file.write(TEST_OUTPUT)
+        test_file.close()
+
+    def test_file_methods(self):
+        target = XProtoTestHelpers.write_tmp_target(
+"""
+  {%% if file_exists("%s") %%}
+    {{ include_file("%s") }}
+  {%% endif %%}
+"""%(TEST_FILE, TEST_FILE)
+        )
+
+        args = FakeArgs()
+        args.inputs = ''
+        args.target = target
+        args.attic = OUTPUT_DIR
+        output = XOSGenerator.generate(args)
+        self.assertIn(TEST_OUTPUT, output)
+
+    def test_xproto_lib(self):
+        target = XProtoTestHelpers.write_tmp_target(
+"""
+  {{ xproto_first_non_empty([None, None, None, None, None, None, "Eureka"]) }}
+""")
+        args = FakeArgs()
+        args.inputs = ''
+        args.target = target
+        output = XOSGenerator.generate(args)
+        self.assertIn("Eureka", output)
+
+    def test_context(self):
+        target = XProtoTestHelpers.write_tmp_target(
+"""
+  {{ context.what }}
+""")
+        args = FakeArgs()
+        args.inputs = ''
+        args.target = target
+        args.kv='what:what is what'
+        output = XOSGenerator.generate(args)
+        self.assertIn("what is what", output)
+
+    def test_singularize(self):
+        proto = \
+"""
+  message TestSingularize {
+      // The following field has an explicitly specified singular
+      required int many = 1 [singular = "one"];
+      // The following fields have automatically computed singulars
+      required int sheep = 2;
+      required int radii = 2;
+      required int slices = 2;
+      required int networks = 2;
+      required int omf_friendlies = 2;
+  }
+"""
+
+        target = XProtoTestHelpers.write_tmp_target(
+"""
+{% for m in proto.messages.0.fields -%}
+{{ xproto_singularize(m) }},
+{%- endfor %}
+""")
+        args = FakeArgs()
+        args.inputs = proto
+        args.target = target
+        output = XOSGenerator.generate(args)
+        self.assertEqual("one,sheep,radius,slice,network,omf_friendly", output.lstrip().rstrip().rstrip(','))
+
+    def test_pluralize(self):
+        proto = \
+"""
+  message TestPluralize {
+      // The following field has an explicitly specified plural
+      required int anecdote = 1 [plural = "data"];
+      // The following fields have automatically computed plurals
+      required int sheep = 2;
+      required int radius = 2;
+      required int slice = 2;
+      required int network = 2;
+      required int omf_friendly = 2;
+  }
+"""
+
+        target = XProtoTestHelpers.write_tmp_target(
+"""
+{% for m in proto.messages.0.fields -%}
+{{ xproto_pluralize(m) }},
+{%- endfor %}
+""")
+        args = FakeArgs()
+        args.inputs = proto
+        args.target = target
+        output = XOSGenerator.generate(args)
+        self.assertEqual("data,sheep,radii,slices,networks,omf_friendlies", output.lstrip().rstrip().rstrip(','))
+
+if __name__ == '__main__':
+    unittest.main()
+
+
diff --git a/lib/xos-genx/xos-genx-tests/test_cli.py b/lib/xos-genx/xos-genx-tests/test_cli.py
new file mode 100644
index 0000000..29098f1
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/test_cli.py
@@ -0,0 +1,55 @@
+
+# Copyright 2017-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
+import os
+from mock import patch
+from xosgenx.xosgen import XosGen
+
+class Args:
+    pass
+
+class XOSGeneratorTest(unittest.TestCase):
+    """
+    Testing the CLI binding for the XOS Generative Toolchain
+    """
+
+    def test_generator(self):
+        """
+        [XOS-GenX] The CLI entry point should correctly parse params
+        """
+        args = Args()
+        args.files = ['lib/xos-genx/xos-genx-tests/xproto/test.xproto']
+        args.target = 'lib/xos-genx/xos-genx-tests/xtarget/test.xtarget'
+        args.output = 'lib/xos-genx/xos-genx-tests/out/dir/'
+        args.write_to_file = "target"
+        args.dest_file = None
+        args.dest_extension = None
+
+        expected_args = Args()
+        expected_args.files = [os.path.abspath(os.getcwd() + '/' + args.files[0])]
+        expected_args.target = os.path.abspath(os.getcwd() + '/' + args.target)
+        expected_args.output = os.path.abspath(os.getcwd() + '/' + args.output)
+
+        with patch("xosgenx.xosgen.XOSGenerator.generate") as generator:
+            XosGen.init(args)
+            actual_args = generator.call_args[0][0]
+            self.assertEqual(actual_args.files, expected_args.files)
+            self.assertEqual(actual_args.target, expected_args.target)
+            self.assertEqual(actual_args.output, expected_args.output)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/lib/xos-genx/xos-genx-tests/test_generator.py b/lib/xos-genx/xos-genx-tests/test_generator.py
new file mode 100644
index 0000000..f59bbfd
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/test_generator.py
@@ -0,0 +1,210 @@
+
+# Copyright 2017-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
+import os
+from helpers import FakeArgs, OUTPUT_DIR
+from xosgenx.generator import XOSGenerator
+
+TEST_EXPECTED_OUTPUT = """
+    name: XOSModel
+    fields:
+            name:
+                type: string
+                description: "Help Name"
+            files:
+                type: string
+                description: "Help Files"
+"""
+
+BASE_XPROTO = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xproto/base.xproto")
+TEST_XPROTO = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xproto/test.xproto")
+SKIP_DJANGO_XPROTO = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xproto/skip_django.xproto")
+VROUTER_XPROTO = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xproto/vrouterport.xproto")
+TEST_TARGET = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xtarget/test.xtarget")
+SPLIT_TARGET = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xtarget/split.xtarget")
+
+TEST_ATTICS = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/attics/")
+
+class XOSGeneratorTest(unittest.TestCase):
+    """
+    Testing the XOS Generative Toolchain
+    """
+
+    def setUp(self):
+        os.chdir(os.path.join(os.path.abspath(os.path.dirname(os.path.realpath(__file__))), "..")) 
+        filesToRemove = [f for f in os.listdir(OUTPUT_DIR)]
+        for f in filesToRemove:
+            if not f.startswith('.'):
+                os.remove(OUTPUT_DIR + '/' + f)
+
+    def test_generator_custom_target_from_file(self):
+        """
+        [XOS-GenX] Generate output from base.xproto
+        """
+        args = FakeArgs()
+        args.files = [TEST_XPROTO]
+        args.target = TEST_TARGET
+        output = XOSGenerator.generate(args)
+        self.assertEqual(output, TEST_EXPECTED_OUTPUT)
+
+    def test_generator_custom_target_from_inputs(self):
+        """
+        [XOS-GenX] Generate output from base.xproto
+        """
+        args = FakeArgs()
+        args.inputs = open(TEST_XPROTO).read()
+        args.target = TEST_TARGET
+        output = XOSGenerator.generate(args)
+        self.assertEqual(output, TEST_EXPECTED_OUTPUT)
+
+    def test_django_with_attic(self):
+        """
+        [XOS-GenX] Generate django output from test.xproto
+        """
+        args = FakeArgs()
+        args.files = [TEST_XPROTO, VROUTER_XPROTO]
+        args.target = 'django.xtarget'
+        args.attic = TEST_ATTICS
+        args.output = OUTPUT_DIR
+        args.dest_extension = 'py'
+        args.write_to_file = 'model'
+        output = XOSGenerator.generate(args)
+
+        # xosmodel has custom header attic
+        self.assertIn('from xosmodel_header import *', output['XOSModel'])
+        self.assertIn('class XOSModel(XOSBase):', output['XOSModel'])
+
+        # vrouter port use the default header
+        self.assertIn('header import *', output['VRouterPort'])
+        self.assertIn('class VRouterPort(XOSBase):', output['VRouterPort'])
+
+        #verify files
+        xosmodel = OUTPUT_DIR + '/xosmodel.py'
+        self.assertTrue(os.path.isfile(xosmodel))
+        xmf = open(xosmodel).read()
+        self.assertIn('from xosmodel_header import *', xmf)
+        self.assertIn('class XOSModel(XOSBase):', xmf)
+
+        vrouterport = OUTPUT_DIR + '/vrouterport.py'
+        self.assertTrue(os.path.isfile(vrouterport))
+        vrpf = open(vrouterport).read()
+        self.assertIn('header import *', vrpf)
+        self.assertIn('class VRouterPort(XOSBase):', vrpf)
+
+    def test_django_with_base(self):
+        args = FakeArgs()
+        args.files = [TEST_XPROTO, BASE_XPROTO]
+        args.target = 'django.xtarget'
+        args.attic = TEST_ATTICS
+        args.output = OUTPUT_DIR
+        args.dest_extension = 'py'
+        args.write_to_file = 'model'
+        output = XOSGenerator.generate(args)
+
+        # verify files
+        xosmodel = OUTPUT_DIR + '/xosmodel.py'
+        self.assertTrue(os.path.isfile(xosmodel))
+        xmf = open(xosmodel).read()
+        self.assertIn('from xosmodel_header import *', xmf)
+        self.assertIn('class XOSModel(XOSBase):', xmf)
+
+        xosbase = OUTPUT_DIR + '/xosbase.py'
+        self.assertTrue(os.path.isfile(xosbase))
+        xbf = open(xosbase).read()
+        self.assertIn('header import *', xbf)
+        self.assertIn('class XOSBase(models.Model, PlModelMixIn):', xbf)
+
+    def test_write_multiple_files(self):
+        """
+        [XOS-GenX] read multiple models as input, print one file per model
+        """
+        args = FakeArgs()
+        args.files = [TEST_XPROTO, VROUTER_XPROTO]
+        args.target = TEST_TARGET
+        args.output = OUTPUT_DIR
+        args.dest_extension = 'txt'
+        args.write_to_file = 'model'
+        XOSGenerator.generate(args)
+
+        generated_files = [f for f in os.listdir(OUTPUT_DIR) if not f.startswith('.')]
+        self.assertEqual(len(generated_files), 2)
+
+        xosmodel = open(os.path.join(OUTPUT_DIR, 'xosmodel.txt'), "r").read()
+        vrouterport = open(os.path.join(OUTPUT_DIR, 'vrouterport.txt'), "r").read()
+
+        self.assertIn("name: XOSModel", xosmodel)
+        self.assertIn("name: VRouterPort", vrouterport)
+
+    def test_write_multiple_files_from_xtarget(self):
+        """
+        [XOS-GenX] read multiple models as input, print separate files based on +++
+        """
+        args = FakeArgs()
+        args.files = [TEST_XPROTO, VROUTER_XPROTO]
+        args.target = SPLIT_TARGET
+        args.output = OUTPUT_DIR
+        args.write_to_file = 'target'
+        XOSGenerator.generate(args)
+
+        generated_files = [f for f in os.listdir(OUTPUT_DIR) if not f.startswith('.')]
+        self.assertEqual(len(generated_files), 2)
+
+        xosmodel = open(os.path.join(OUTPUT_DIR, 'xosmodel.txt'), "r").read()
+        vrouterport = open(os.path.join(OUTPUT_DIR, 'vrouterport.txt'), "r").read()
+
+        self.assertIn("name: XOSModel", xosmodel)
+        self.assertIn("name: VRouterPort", vrouterport)
+
+    def test_skip_django(self):
+        args = FakeArgs()
+        args.files = [SKIP_DJANGO_XPROTO]
+        args.target = 'django.xtarget'
+        args.output = OUTPUT_DIR
+        args.dest_extension = 'py'
+        args.write_to_file = 'model'
+        output = XOSGenerator.generate(args)
+
+        # should not print a file if options.skip_django = True
+        file = OUTPUT_DIR + '/user.py'
+        self.assertFalse(os.path.isfile(file))
+
+    def test_service_order(self):
+        args = FakeArgs()
+        args.files = [BASE_XPROTO, TEST_XPROTO, VROUTER_XPROTO]
+        args.target = 'service.xtarget'
+        args.output = OUTPUT_DIR
+        args.write_to_file = 'target'
+        output = XOSGenerator.generate(args)
+
+        model = OUTPUT_DIR + '/models.py'
+        self.assertTrue(os.path.isfile(model))
+        line_num = 0
+
+        for line in open(model).readlines():
+            line_num += 1
+            if line.find('class XOSBase(models.Model, PlModelMixIn):') >= 0:
+                base_line = line_num
+            if line.find('XOSModel(XOSBase):') >= 0:
+                xosmodel_line = line_num
+            if line.find('class VRouterPort(XOSBase):') >= 0:
+                vrouter_line = line_num
+        self.assertLess(base_line, xosmodel_line)
+        self.assertLess(xosmodel_line, vrouter_line)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/lib/xos-genx/xos-genx-tests/tosca_test.py b/lib/xos-genx/xos-genx-tests/tosca_test.py
new file mode 100644
index 0000000..48a4db9
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/tosca_test.py
@@ -0,0 +1,91 @@
+# Copyright 2017-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 xosgenx.generator import XOSGenerator
+from helpers import FakeArgs, XProtoTestHelpers
+
+
+class XProtoToscaTest(unittest.TestCase):
+
+    def setUp(self):
+        self.target = XProtoTestHelpers.write_tmp_target(
+"""
+{%- for m in proto.messages %}
+    {{ xproto_fields_to_tosca_keys(m.fields) }}
+{% endfor -%}
+""")
+
+    def test_xproto_fields_to_tosca_keys_default(self):
+        """
+        [XOS-GenX] if no "tosca_key" is specified, and a name attribute is present in the model, use that
+        """
+        xproto = \
+"""
+option app_label = "test";
+
+message Foo {
+    required string name = 1 [ null = "False", blank="False"];
+}
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+        output = XOSGenerator.generate(args)
+        self.assertIn('name', output)
+
+    def test_xproto_fields_to_tosca_keys_custom(self):
+        """
+        [XOS-GenX] if "tosca_key" is specified, use it
+        """
+        xproto = \
+            """
+            option app_label = "test";
+        
+            message Foo {
+                required string name = 1 [ null = "False", blank="False"];
+                required string key_1 = 2 [ null = "False", blank="False", tosca_key=True];
+                required string key_2 = 3 [ null = "False", blank="False", tosca_key=True];
+            }
+            """
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+        output = XOSGenerator.generate(args)
+        self.assertNotIn('name', output)
+        self.assertIn('key_1', output)
+        self.assertIn('key_2', output)
+
+    def test_xproto_fields_link_to_tosca_keys_custom(self):
+        """
+        [XOS-GenX] if "tosca_key" is specified, use it
+        """
+        xproto = \
+            """
+            option app_label = "test";
+
+            message Foo {
+                required string name = 1 [ null = "False", blank="False"];
+                required manytoone provider_service_instance->ServiceInstance:provided_links = 1 [db_index = True, null = False, blank = False, tosca_key=True];
+            }
+            """
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+        output = XOSGenerator.generate(args)
+        self.assertNotIn('name', output)
+        self.assertIn('provider_service_instance_id', output)
\ No newline at end of file
diff --git a/lib/xos-genx/xos-genx-tests/translator_test.py b/lib/xos-genx/xos-genx-tests/translator_test.py
new file mode 100644
index 0000000..48c1a81
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/translator_test.py
@@ -0,0 +1,321 @@
+
+# Copyright 2017-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
+import os
+from xosgenx.generator import XOSGenerator
+from helpers import FakeArgs
+import yaml
+
+PROTO_EXPECTED_OUTPUT = """
+message VRouterPort {
+  option bases = "XOSBase";
+  optional string name = 1 [ null = "True",  max_length = "20",  blank = "True",  help_text = ""port friendly name"",  modifier = "optional",  db_index = "False" ];
+  required string openflow_id = 2 [ null = "False",  max_length = "21",  blank = "False",  help_text = ""port identifier in ONOS"",  modifier = "required",  db_index = "False" ];
+  required int32 vrouter_device = 3 [ null = "False",  blank = "False",  model = "VRouterDevice",  modifier = "required",  type = "link",  port = "ports",  link_type = "manytoone",  db_index = "True" ];
+  required int32 vrouter_service = 4 [ null = "False",  blank = "False",  model = "VRouterService",  modifier = "required",  type = "link",  port = "device_ports",  link_type = "manytoone",  db_index = "True" ];
+}
+"""
+VROUTER_XPROTO = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xproto/vrouterport.xproto")
+
+# Generate other formats from xproto
+class XProtoTranslatorTest(unittest.TestCase):
+    def _test_proto_generator(self):
+        args = FakeArgs()
+        args.files = [VROUTER_XPROTO]
+        args.target = 'proto.xtarget'
+        output = XOSGenerator.generate(args)
+        self.assertEqual(output, PROTO_EXPECTED_OUTPUT)
+
+    def test_yaml_generator(self):
+        xproto = \
+"""
+option app_label = "test";
+
+message Port (PlCoreBase,ParameterMixin){
+     required manytoone network->Network:links = 1 [db_index = True, null = False, blank = False];
+     optional manytoone instance->Instance:ports = 2 [db_index = True, null = True, blank = True];
+     optional string ip = 3 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     optional string port_id = 4 [help_text = "Neutron port id", max_length = 256, null = True, db_index = False, blank = True];
+     optional string mac = 5 [help_text = "MAC address associated with this port", max_length = 256, null = True, db_index = False, blank = True];
+     required bool xos_created = 6 [default = False, null = False, db_index = False, blank = True];
+}
+
+message Instance (PlCoreBase){
+     optional string instance_id = 1 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance id", null = True, db_index = False];
+     optional string instance_uuid = 2 [max_length = 200, content_type = "stripped", blank = True, help_text = "Nova instance uuid", null = True, db_index = False];
+     required string name = 3 [max_length = 200, content_type = "stripped", blank = False, help_text = "Instance name", null = False, db_index = False];
+     optional string instance_name = 4 [max_length = 200, content_type = "stripped", blank = True, help_text = "OpenStack generated name", null = True, db_index = False];
+     optional string ip = 5 [max_length = 39, content_type = "ip", blank = True, help_text = "Instance ip address", null = True, db_index = False];
+     required manytoone image->Image:instances = 6 [db_index = True, null = False, blank = False];
+     optional manytoone creator->User:instances = 7 [db_index = True, null = True, blank = True];
+     required manytoone slice->Slice:instances = 8 [db_index = True, null = False, blank = False];
+     required manytoone deployment->Deployment:instance_deployment = 9 [db_index = True, null = False, blank = False];
+     required manytoone node->Node:instances = 10 [db_index = True, null = False, blank = False];
+     required int32 numberCores = 11 [help_text = "Number of cores for instance", default = 0, null = False, db_index = False, blank = False];
+     required manytoone flavor->Flavor:instance = 12 [help_text = "Flavor of this instance", default = "get_default_flavor()", null = False, db_index = True, blank = False];
+     optional string userData = 13 [help_text = "user_data passed to instance during creation", null = True, db_index = False, blank = True];
+     required string isolation = 14 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+     optional string volumes = 15 [help_text = "Comma-separated list of directories to expose to parent context", null = True, db_index = False, blank = True];
+     optional manytoone parent->Instance:instance = 16 [help_text = "Parent Instance for containers nested inside of VMs", null = True, db_index = True, blank = True];
+     required manytomany tags->Tag = 17 [db_index = False, null = False, blank = True];
+}
+
+message Network (PlCoreBase,ParameterMixin) {
+     required string name = 1 [db_index = False, max_length = 32, null = False, blank = False];
+     required manytoone template->NetworkTemplate:network = 2 [db_index = True, null = False, blank = False];
+     required string subnet = 3 [db_index = False, max_length = 32, null = False, blank = True];
+     required string start_ip = 4 [db_index = False, max_length = 32, null = False, blank = True];
+     required string end_ip = 5 [db_index = False, max_length = 32, null = False, blank = True];
+     optional string ports = 6 [db_index = False, max_length = 1024, null = True, blank = True];
+     optional string labels = 7 [db_index = False, max_length = 1024, null = True, blank = True];
+     required manytoone owner->Slice:ownedNetworks = 8 [help_text = "Slice that owns control of this Network", null = False, db_index = True, blank = False];
+     required int32 guaranteed_bandwidth = 9 [default = 0, null = False, db_index = False, blank = False];
+     required bool permit_all_slices = 10 [default = False, null = False, db_index = False, blank = True];
+     optional string topology_parameters = 11 [db_index = False, null = True, blank = True];
+     optional string controller_url = 12 [db_index = False, max_length = 1024, null = True, blank = True];
+     optional string controller_parameters = 13 [db_index = False, null = True, blank = True];
+     optional string network_id = 14 [help_text = "Quantum network", max_length = 256, null = True, db_index = False, blank = True];
+     optional string router_id = 15 [help_text = "Quantum router id", max_length = 256, null = True, db_index = False, blank = True];
+     optional string subnet_id = 16 [help_text = "Quantum subnet id", max_length = 256, null = True, db_index = False, blank = True];
+     required bool autoconnect = 17 [help_text = "This network can be autoconnected to the slice that owns it", default = True, null = False, db_index = False, blank = True];
+     required manytomany permitted_slices->Slice/Network_permitted_slices:availableNetworks = 18 [db_index = False, null = False, blank = True];
+     required manytomany slices->Slice/NetworkSlice:networks = 19 [db_index = False, null = False, blank = True];
+     required manytomany instances->Instance/Port:networks = 20 [db_index = False, null = False, blank = True];
+}
+
+message Slice (PlCoreBase){
+     required string name = 1 [max_length = 80, content_type = "stripped", blank = False, help_text = "The Name of the Slice", null = False, db_index = False];
+     required bool enabled = 2 [help_text = "Status for this Slice", default = True, null = False, db_index = False, blank = True];
+     required bool omf_friendly = 3 [default = False, null = False, db_index = False, blank = True];
+     required string description = 4 [help_text = "High level description of the slice and expected activities", max_length = 1024, null = False, db_index = False, blank = True];
+     required string slice_url = 5 [db_index = False, max_length = 512, null = False, content_type = "url", blank = True];
+     required manytoone site->Site:slices = 6 [help_text = "The Site this Slice belongs to", null = False, db_index = True, blank = False];
+     required int32 max_instances = 7 [default = 10, null = False, db_index = False, blank = False];
+     optional manytoone service->Service:slices = 8 [db_index = True, null = True, blank = True];
+     optional string network = 9 [blank = True, max_length = 256, null = True, db_index = False, choices = "((None, 'Default'), ('host', 'Host'), ('bridged', 'Bridged'), ('noauto', 'No Automatic Networks'))"];
+     optional string exposed_ports = 10 [db_index = False, max_length = 256, null = True, blank = True];
+     optional manytoone serviceClass->ServiceClass:slices = 11 [db_index = True, null = True, blank = True];
+     optional manytoone creator->User:slices = 12 [db_index = True, null = True, blank = True];
+     optional manytoone default_flavor->Flavor:slices = 13 [db_index = True, null = True, blank = True];
+     optional manytoone default_image->Image:slices = 14 [db_index = True, null = True, blank = True];
+     optional manytoone default_node->Node:slices = 15 [db_index = True, null = True, blank = True];
+     optional string mount_data_sets = 16 [default = "GenBank", max_length = 256, content_type = "stripped", blank = True, null = True, db_index = False];
+     required string default_isolation = 17 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+     required manytomany tags->Tag = 18 [db_index = False, null = False, blank = True];
+}
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = 'modeldefs.xtarget'
+        output = XOSGenerator.generate(args)
+
+        yaml_ir = yaml.load(output)
+        self.assertEqual(len(yaml_ir['items']), 4)
+
+    def test_gui_hidden_models(self):
+        xproto = \
+"""
+option app_label = "test";
+
+message Foo {
+    option gui_hidden = True;
+    required string name = 1 [ null = "False", blank="False"];
+}
+
+message Bar {
+    option gui_hidden = "False";
+    required string name = 1 [ null = "False", blank="False"];
+}
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = 'modeldefs.xtarget'
+        output = XOSGenerator.generate(args)
+        yaml_ir = yaml.load(output)
+        self.assertEqual(len(yaml_ir['items']), 1)
+        self.assertIn('Bar', output)
+        self.assertNotIn('Foo', output)
+
+    def test_gui_hidden_model_fields(self):
+        xproto = \
+"""
+option app_label = "test";
+
+message Foo {
+    required string name = 1 [ null = "False", blank="False"];
+    required string secret = 1 [ null = "False", blank="False", gui_hidden = "True"];
+}
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = 'modeldefs.xtarget'
+        output = XOSGenerator.generate(args)
+        yaml_ir = yaml.load(output)
+        self.assertEqual(len(yaml_ir['items']), 1)
+        self.assertIn('name', output)
+        self.assertNotIn('secret', output)
+
+    def test_static_options(self):
+        xproto = \
+"""
+option app_label = "test";
+
+message Foo {
+    required string name = 1 [ null = "False", blank="False"];
+    required string isolation = 14 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+}
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = 'modeldefs.xtarget'
+        output = XOSGenerator.generate(args)
+        self.assertIn("options:", output)
+        self.assertIn(" {'id': 'container_vm', 'label': 'Container In VM'}", output)
+
+    def test_not_static_options(self):
+        xproto = \
+"""
+option app_label = "test";
+
+message Foo {
+    required string name = 1 [ null = "False", blank="False"];
+}
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = 'modeldefs.xtarget'
+        output = XOSGenerator.generate(args)
+        self.assertNotIn("options:", output)
+
+    def test_default_value_in_modeldef(self):
+        xproto = \
+"""
+option app_label = "test";
+
+message Foo {
+    required string name = 1 [ null = "False", blank="False", default = "bar"];
+    required string falsetrue = 1 [ null = "False", blank="False", default = False];
+    required string truefalse = 1 [ null = "False", blank="False", default = True];
+    required string some = 1 [ null = "False", blank="False", default = None];
+    required string zero = 1 [ null = "False", blank="False", default = 0];
+}
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = 'modeldefs.xtarget'
+        output = XOSGenerator.generate(args)
+        self.assertIn('default: "bar"', output)
+        self.assertIn('default: "false"', output)
+        self.assertIn('default: "true"', output)
+        self.assertIn('default: "null"', output)
+        self.assertIn('default: "0"', output)
+
+    def test_not_default_value_in_modeldef(self):
+        xproto = \
+"""
+option app_label = "test";
+
+message Foo {
+    required string name = 1 [ null = "False", blank="False"];
+}
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = 'modeldefs.xtarget'
+        output = XOSGenerator.generate(args)
+        self.assertNotIn('default:', output)
+
+    def test_one_to_many_in_modeldef(self):
+        xproto = \
+"""
+option app_label = "test";
+
+message ServiceDependency {
+    required manytoone provider_service->Service:provided_dependencies = 1;
+    required manytoone subscriber_service->Service:subscribed_dependencies = 2;
+}
+
+message Service {
+    required string name = 1;
+}
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = 'modeldefs.xtarget'
+        output = XOSGenerator.generate(args)
+        # Service deps model
+        self.assertIn('{model: Service, type: manytoone, on_field: provider_service}', output)
+        self.assertIn('{model: Service, type: manytoone, on_field: provider_service}', output)
+
+        # Service model
+        self.assertIn('{model: ServiceDependency, type: onetomany, on_field: provider_service}', output)
+        self.assertIn('{model: ServiceDependency, type: onetomany, on_field: provider_service}', output)
+
+    def test_model_description(self):
+        xproto = \
+"""
+option app_label = "test";
+
+message Foo {
+    option description="This is the Foo model";
+    required string name = 1 [ null = "False", blank="False"];
+    required string isolation = 14 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+}
+
+message Bar {
+    required string name = 1;
+}
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = 'modeldefs.xtarget'
+        output = XOSGenerator.generate(args)
+        self.assertIn('description: "This is the Foo model"', output)
+
+    def test_model_verbose_name(self):
+        xproto = \
+"""
+option app_label = "test";
+
+message Foo {
+    option verbose_name="Verbose Foo Name";
+    required string name = 1 [ null = "False", blank="False"];
+    required string isolation = 14 [default = "vm", choices = "(('vm', 'Virtual Machine'), ('container', 'Container'), ('container_vm', 'Container In VM'))", max_length = 30, blank = False, null = False, db_index = False];
+}
+
+message Bar {
+    required string name = 1;
+}
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = 'modeldefs.xtarget'
+        output = XOSGenerator.generate(args)
+        self.assertIn('verbose_name: "Verbose Foo Name"', output)
+
+if __name__ == '__main__':
+    unittest.main()
+
+
diff --git a/lib/xos-genx/xos-genx-tests/xos_security_test.py b/lib/xos-genx/xos-genx-tests/xos_security_test.py
new file mode 100644
index 0000000..a07bc7b
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/xos_security_test.py
@@ -0,0 +1,202 @@
+
+# Copyright 2017-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 xosgenx.generator import XOSGenerator
+from helpers import FakeArgs, XProtoTestHelpers
+import pdb
+import mock
+
+"""The function below is for eliminating warnings arising due to the missing policy_output_enforcer,
+which is generated and loaded dynamically.
+"""
+def policy_output_enforcer(x, y):
+    raise Exception("Security enforcer not generated. Test failed.")
+    return False
+
+"""
+The tests below use the Python code target to generate 
+Python security policies, set up an appropriate environment and execute the Python.
+The security policies here deliberately made complex in order to stress the processor.
+"""
+class XProtoXOSSecurityTest(unittest.TestCase):
+    def setUp(self):
+        self.target = XProtoTestHelpers.write_tmp_target("{{ xproto_fol_to_python_test('output',proto.policies.test_policy, None, '0') }}")
+
+    """
+    This is the security policy for controllers
+    """
+    def test_controller_policy(self):
+        xproto = \
+"""
+    policy test_policy < ctx.user.is_admin | exists Privilege: Privilege.accessor_id = ctx.user.id & Privilege.object_type = "Deployment" & Privilege.permission = "role:admin" & Privilege.object_id = obj.id >
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def policy_output_enforcer(obj, ctx):
+            i2 = ctx.user.is_admin
+            i3 = Privilege.objects.filter(Q(accessor_id=ctx.user.id), Q(object_type='Deployment'), Q(permission='role:admin'), Q(object_id=obj.id))[0]
+            i1 = (i2 or i3)
+                return i1
+        """
+
+        # FIXME: Test this policy by executing it
+        self.assertTrue(policy_output_enforcer is not None)
+
+    """
+    This is the security policy for ControllerNetworks
+    """
+    def test_controller_network_policy(self):
+        xproto = \
+"""
+    policy test_policy < 
+         ctx.user.is_admin
+         | (exists Privilege:
+             Privilege.accessor_id = ctx.user.id
+             & Privilege.accessor_type = "User"
+             & Privilege.object_type = "Slice"
+             & Privilege.object_id = obj.owner.id)
+         | (exists Privilege:
+             Privilege.accessor_id = ctx.user.id
+             & Privilege.accessor_type = "User"
+             & Privilege.object_type = "Site"
+             & Privilege.object_id = obj.owner.site.id
+             & Privilege.permission = "role:admin") >
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def policy_output_enforcer(obj, ctx):
+            i2 = ctx.user.is_admin
+            i4 = Privilege.objects.filter(Q(accessor_id=ctx.user.id), Q(accessor_type='User'), Q(object_type='Slice'), Q(object_id=obj.owner.id))[0]
+            i5 = Privilege.objects.filter(Q(accessor_id=ctx.user.id), Q(accessor_type='User'), Q(object_type='Site'), Q(object_id=obj.owner.site.id), Q(permission='role:admin'))[0]
+            i3 = (i4 or i5)
+            i1 = (i2 or i3)
+            return i1
+        """
+
+        # FIXME: Test this policy by executing it
+        self.assertTrue(policy_output_enforcer is not None)
+
+    """
+    This is the security policy for Slices
+    """
+    def test_slice_policy(self):
+        xproto = \
+"""
+   policy site_policy <
+            ctx.user.is_admin
+            | (ctx.write_access -> exists Privilege: Privilege.object_type = "Site" & Privilege.object_id = obj.id & Privilege.accessor_id = ctx.user.id & Privilege.permission_id = "role:admin") >
+
+   policy test_policy <
+         ctx.user.is_admin
+         | (*site_policy(site)
+         & ((exists Privilege:
+             Privilege.accessor_id = ctx.user.id
+             & Privilege.accessor_type = "User"
+             & Privilege.object_type = "Slice"
+             & Privilege.object_id = obj.id
+             & (ctx.write_access->Privilege.permission="role:admin"))
+           | (exists Privilege:
+             Privilege.accessor_id = ctx.user.id
+             & Privilege.accessor_type = "User"
+             & Privilege.object_type = "Site"
+             & Privilege.object_id = obj.site.id
+             & Privilege.permission = "role:admin"))
+            )>
+    
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def policy_output_enforcer(obj, ctx):
+	    i2 = ctx.user.is_admin
+	    i4 = policy_site_policy_enforcer(obj.site, ctx)
+	    i10 = ctx.write_access
+	    i11 = (not (not Privilege.objects.filter(Q(accessor_id=ctx.user.id), Q(accessor_type='User'), Q(object_type='Slice'), Q(object_id=obj.id), Q(permission='role:admin'))))
+	    i8 = (i10 and i11)
+	    i14 = ctx.write_access
+	    i12 = (not i14)
+	    i13 = (not (not Privilege.objects.filter(Q(accessor_id=ctx.user.id), Q(accessor_type='User'), Q(object_type='Slice'), Q(object_id=obj.id))))
+	    i9 = (i12 and i13)
+	    i6 = (i8 or i9)
+	    i7 = (not (not Privilege.objects.filter(Q(accessor_id=ctx.user.id), Q(accessor_type='User'), Q(object_type='Site'), Q(object_id=obj.site.id), Q(permission='role:admin'))))
+	    i5 = (i6 or i7)
+	    i3 = (i4 and i5)
+	    i1 = (i2 or i3)
+	    return i1
+        """
+
+        # FIXME: Test this policy by executing it
+        self.assertTrue(policy_output_enforcer is not None)
+
+    """
+    This is the security policy for Users
+    """
+    def test_user_policy(self):
+        xproto = \
+"""
+    policy test_policy <
+         ctx.user.is_admin
+         | ctx.user.id = obj.id
+         | (exists Privilege: 
+             Privilege.accessor_id = ctx.user.id
+             & Privilege.accessor_type = "User"
+             & Privilege.permission = "role:admin"
+             & Privilege.object_type = "Site"
+             & Privilege.object_id = ctx.user.site.id) >
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def policy_output_enforcer(obj, ctx):
+            i2 = ctx.user.is_admin
+            i4 = (ctx.user.id == obj.id)
+            i5 = Privilege.objects.filter(Q(accessor_id=ctx.user.id), Q(accessor_type='User'), Q(permission='role:admin'), Q(object_type='Site'), Q(object_id=ctx.user.site.id))[0]
+            i3 = (i4 or i5)
+            i1 = (i2 or i3)
+            return i1
+        """
+
+        # FIXME: Test this policy by executing it
+        self.assertTrue(policy_output_enforcer is not None)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/lib/xos-genx/xos-genx-tests/xos_validation_test.py b/lib/xos-genx/xos-genx-tests/xos_validation_test.py
new file mode 100644
index 0000000..69dafc5
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/xos_validation_test.py
@@ -0,0 +1,224 @@
+
+# Copyright 2017-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 xosgenx.generator import XOSGenerator
+from helpers import FakeArgs, XProtoTestHelpers
+
+"""The function below is for eliminating warnings arising due to the missing policy_output_validator,
+which is generated and loaded dynamically.
+"""
+def policy_output_validator(x, y):
+    raise Exception("Validator not generated. Test failed.")
+    return False
+
+"""
+The tests below use the Python code target to generate 
+Python validation policies, set up an appropriate environment and execute the Python.
+"""
+class XProtoXOSModelValidationTest(unittest.TestCase):
+    def setUp(self):
+        self.target = XProtoTestHelpers.write_tmp_target("{{ xproto_fol_to_python_validator('output', proto.policies.test_policy, None, 'Necessary Failure') }}")
+
+    def test_instance_container(self):
+        xproto = \
+"""
+    policy test_policy < (obj.isolation = "container" | obj.isolation = "container_vm" ) -> (obj.image.kind = "container") >
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+
+        obj = FakeArgs()
+        obj.isolation = 'container'
+        obj.kind = 'not a container'
+
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def policy_output_validator(obj, ctx):
+            i4 = (obj.isolation == 'container')
+            i5 = (self.isolation == 'container_vm')
+            i2 = (i4 or i5)
+            i3 = (obj.image.kind == 'container')
+            i1 = (i2 or i3)
+            return i1
+        """
+
+        with self.assertRaises(Exception):
+           policy_output_validator(obj, {})
+    
+    def test_slice_name_validation(self):
+        xproto = \
+"""
+    policy test_policy < not obj.id -> {{ obj.name.startswith(obj.site.login_base) }} >
+"""
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+
+        obj = FakeArgs()
+        obj.isolation = 'container'
+        obj.kind = 'not a container'
+
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def policy_output_validator(obj, ctx):
+            i3 = obj.id
+            i4 = obj.name.startswith(obj.site.login_base)
+            i2 = ((not i3) or i4)
+            i1 = (not i2)
+            if (not i1):
+                raise ValidationError('Necessary Failure')
+        """
+
+        with self.assertRaises(Exception):
+           policy_output_validator(obj, {})
+
+    def test_equal(self):
+        xproto = \
+"""
+    policy test_policy < not (ctx.user = obj.user) >
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def policy_output_validator(obj, ctx):
+            i2 = (ctx.user == obj.user)
+            i1 = (not i2)
+            if (not i1):
+                raise Exception('Necessary Failure')
+        """
+
+        obj = FakeArgs()
+	obj.user = 1
+        ctx = FakeArgs()
+	ctx.user = 1
+
+        with self.assertRaises(Exception):
+           policy_output_validator(obj, ctx)
+
+    def test_bin(self):
+        xproto = \
+"""
+    policy test_policy < not (ctx.is_admin = True | obj.empty = True) | False>
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def policy_output_validator(obj, ctx):
+            i2 = (ctx.is_admin == True)
+            i3 = (obj.empty == True)
+            i1 = (i2 or i3)
+            if (not i1):
+                raise Exception('Necessary Failure')
+        """
+
+        obj = FakeArgs()
+	obj.empty = True
+
+	ctx = FakeArgs()
+	ctx.is_admin = True
+
+        with self.assertRaises(Exception):
+            verdict = policy_output_validator(obj, ctx)
+
+        
+    def test_exists(self):
+        xproto = \
+"""
+    policy test_policy < exists Privilege: Privilege.object_id = obj.id >
+"""
+	args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def policy_output_validator(obj, ctx):
+            i1 = Privilege.objects.filter(Q(object_id=obj.id))[0]
+            if (not i1):
+                raise Exception('Necessary Failure')
+        """
+
+        self.assertTrue(policy_output_validator is not None)
+	
+    def test_python(self):
+        xproto = \
+"""
+    policy test_policy < {{ "jack" in ["the", "box"] }} = True >
+"""
+	args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+        output = XOSGenerator.generate(args)
+        exec(output) # This loads the generated function, which should look like this:
+
+        """
+        def policy_output_validator(obj, ctx):
+            i2 = ('jack' in ['the', 'box'])
+            i1 = (i2 == True)
+            if (not i1):
+                raise Exception('Necessary Failure')
+        """
+
+        with self.assertRaises(Exception):
+            self.assertTrue(policy_output_validator({}, {}) is True)
+
+    def test_forall(self):
+        # This one we only parse
+        xproto = \
+"""
+    policy test_policy < forall Credential: Credential.obj_id = obj_id >
+"""
+
+        args = FakeArgs()
+        args.inputs = xproto
+        args.target = self.target
+
+        output = XOSGenerator.generate(args)
+
+        """
+        def policy_output_enforcer(obj, ctx):
+            i2 = Credential.objects.filter((~ Q(obj_id=obj_id)))[0]
+            i1 = (not i2)
+            return i1
+        """
+
+        self.assertIn('policy_output_validator', output)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/lib/xos-genx/xos-genx-tests/xproto/base.xproto b/lib/xos-genx/xos-genx-tests/xproto/base.xproto
new file mode 100644
index 0000000..78cc4e8
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/xproto/base.xproto
@@ -0,0 +1,18 @@
+option app_name = "core";
+
+message XOSBase {
+     option skip_init = True;
+     required string created = 1 [content_type = "date", auto_now_add = True];
+     required string updated = 2 [default = "now()", content_type = "date"];
+     optional string enacted = 3 [null = True, content_type = "date", blank = True, default = None];
+     optional string policed = 4 [null = True, content_type = "date", blank = True, default = None];
+     optional string backend_register = 5 [default = "{}", max_length = 1024, null = True];
+     required bool backend_need_delete = 6 [default = False];
+     required bool backend_need_reap = 7 [default = False];
+     required string backend_status = 8 [default = "0 - Provisioning in progress", max_length = 1024];
+     required bool deleted = 9 [default = False];
+     required bool write_protect = 10 [default = False];
+     required bool lazy_blocked = 11 [default = False];
+     required bool no_sync = 12 [default = False];
+     required bool no_policy = 13 [default = False];
+}
\ No newline at end of file
diff --git a/lib/xos-genx/xos-genx-tests/xproto/skip_django.xproto b/lib/xos-genx/xos-genx-tests/xproto/skip_django.xproto
new file mode 100644
index 0000000..8dd1039
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/xproto/skip_django.xproto
@@ -0,0 +1,4 @@
+message User (AbstractBaseUser,PlModelMixIn) {
+     option skip_django = True;
+     required string email = 1 [db_index = True, max_length = 255, null = False, blank = False];
+}
\ No newline at end of file
diff --git a/lib/xos-genx/xos-genx-tests/xproto/test.xproto b/lib/xos-genx/xos-genx-tests/xproto/test.xproto
new file mode 100644
index 0000000..54420fa
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/xproto/test.xproto
@@ -0,0 +1,4 @@
+message XOSModel (XOSBase) {
+     required string name = 1 [max_length = 200, content_type = "stripped", blank = False, help_text = "Help Name", null = False, db_index = False];
+     required string files = 2 [max_length = 1024, content_type = "stripped", blank = False, help_text = "Help Files", null = False, db_index = False];
+}
\ No newline at end of file
diff --git a/lib/xos-genx/xos-genx-tests/xproto/vrouterport.xproto b/lib/xos-genx/xos-genx-tests/xproto/vrouterport.xproto
new file mode 100644
index 0000000..1b092ac
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/xproto/vrouterport.xproto
@@ -0,0 +1,6 @@
+message VRouterPort (XOSBase){
+     optional string name = 1 [help_text = "port friendly name", max_length = 20, null = True, db_index = False, blank = True];
+     required string openflow_id = 2 [help_text = "port identifier in ONOS", max_length = 21, null = False, db_index = False, blank = False];
+     required manytoone vrouter_device->VRouterDevice:ports = 3 [db_index = True, null = False, blank = False];
+     required manytoone vrouter_service->VRouterService:device_ports = 4 [db_index = True, null = False, blank = False];
+}
\ No newline at end of file
diff --git a/lib/xos-genx/xos-genx-tests/xtarget/split.xtarget b/lib/xos-genx/xos-genx-tests/xtarget/split.xtarget
new file mode 100644
index 0000000..2d55f43
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/xtarget/split.xtarget
@@ -0,0 +1,10 @@
+{% for m in proto.messages %}
+    name: {{ m.name }}
+    fields:
+            {%- for f in m.fields %}
+            {{ f.name }}:
+                type: {{ f.type }}
+                description: {{ f.options.help_text }}
+            {%- endfor %}
++++ {{ m.name }}.txt
+{% endfor %}
diff --git a/lib/xos-genx/xos-genx-tests/xtarget/test.xtarget b/lib/xos-genx/xos-genx-tests/xtarget/test.xtarget
new file mode 100644
index 0000000..658784c
--- /dev/null
+++ b/lib/xos-genx/xos-genx-tests/xtarget/test.xtarget
@@ -0,0 +1,9 @@
+{% for m in proto.messages %}
+    name: {{ m.name }}
+    fields:
+            {%- for f in m.fields %}
+            {{ f.name }}:
+                type: {{ f.type }}
+                description: {{ f.options.help_text }}
+            {%- endfor %}
+{% endfor %}
\ No newline at end of file