blob: 8212d515dae5885192edc2a3a109974292a55fa6 [file] [log] [blame]
Matteo Scandolod2044a42017-08-07 16:08:28 -07001# Copyright 2017-present Open Networking Foundation
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15
Zack Williams9a42f872019-02-15 17:56:04 -070016from __future__ import absolute_import
Matteo Scandolo67654fa2017-06-09 09:33:17 -070017import unittest
18import os
Scott Baker1f7791d2018-10-04 13:21:20 -070019from helpers import OUTPUT_DIR
20from xosgenx.generator import XOSProcessor, XOSProcessorArgs
Matteo Scandolo67654fa2017-06-09 09:33:17 -070021
22TEST_EXPECTED_OUTPUT = """
23 name: XOSModel
24 fields:
25 name:
26 type: string
27 description: "Help Name"
28 files:
29 type: string
30 description: "Help Files"
31"""
32
Zack Williams045b63d2019-01-22 16:30:57 -070033BASE_XPROTO = os.path.abspath(
34 os.path.dirname(os.path.realpath(__file__)) + "/xproto/base.xproto"
35)
36TEST_XPROTO = os.path.abspath(
37 os.path.dirname(os.path.realpath(__file__)) + "/xproto/test.xproto"
38)
39FIELDTEST_XPROTO = os.path.abspath(
40 os.path.dirname(os.path.realpath(__file__)) + "/xproto/fieldtest.xproto"
41)
42REVERSEFIELDTEST_XPROTO = os.path.abspath(
43 os.path.dirname(os.path.realpath(__file__)) + "/xproto/reversefieldtest.xproto"
44)
45FILTERTEST_XPROTO = os.path.abspath(
46 os.path.dirname(os.path.realpath(__file__)) + "/xproto/filtertest.xproto"
47)
48SKIP_DJANGO_XPROTO = os.path.abspath(
49 os.path.dirname(os.path.realpath(__file__)) + "/xproto/skip_django.xproto"
50)
51VROUTER_XPROTO = os.path.abspath(
52 os.path.dirname(os.path.realpath(__file__)) + "/xproto/vrouterport.xproto"
53)
54TEST_TARGET = os.path.abspath(
55 os.path.dirname(os.path.realpath(__file__)) + "/xtarget/test.xtarget"
56)
57FIELDTEST_TARGET = os.path.abspath(
58 os.path.dirname(os.path.realpath(__file__)) + "/xtarget/fieldtest.xtarget"
59)
60FILTERTEST_TARGET = os.path.abspath(
61 os.path.dirname(os.path.realpath(__file__)) + "/xtarget/filtertest.xtarget"
62)
63SPLIT_TARGET = os.path.abspath(
64 os.path.dirname(os.path.realpath(__file__)) + "/xtarget/split.xtarget"
65)
Matteo Scandolo67654fa2017-06-09 09:33:17 -070066
67TEST_ATTICS = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/attics/")
68
Zack Williams045b63d2019-01-22 16:30:57 -070069
Sapan Bhatiabfb233a2018-02-09 14:53:09 -080070class XOSProcessorTest(unittest.TestCase):
Matteo Scandolo67654fa2017-06-09 09:33:17 -070071 """
72 Testing the XOS Generative Toolchain
73 """
74
75 def setUp(self):
Zack Williams045b63d2019-01-22 16:30:57 -070076 os.chdir(
77 os.path.join(
78 os.path.abspath(os.path.dirname(os.path.realpath(__file__))), ".."
79 )
80 )
Matteo Scandolo67654fa2017-06-09 09:33:17 -070081 filesToRemove = [f for f in os.listdir(OUTPUT_DIR)]
82 for f in filesToRemove:
Zack Williams045b63d2019-01-22 16:30:57 -070083 if not f.startswith("."):
84 os.remove(OUTPUT_DIR + "/" + f)
Matteo Scandolo67654fa2017-06-09 09:33:17 -070085
Sapan Bhatia4c835602017-07-14 01:13:17 -040086 def test_generator_custom_target_from_file(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -070087 """
88 [XOS-GenX] Generate output from base.xproto
89 """
Zack Williams045b63d2019-01-22 16:30:57 -070090 args = XOSProcessorArgs(files=[TEST_XPROTO], target=TEST_TARGET)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -080091 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -070092 self.assertEqual(output, TEST_EXPECTED_OUTPUT)
93
Sapan Bhatia4c835602017-07-14 01:13:17 -040094 def test_generator_custom_target_from_inputs(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -070095 """
96 [XOS-GenX] Generate output from base.xproto
97 """
Zack Williams045b63d2019-01-22 16:30:57 -070098 args = XOSProcessorArgs(inputs=open(TEST_XPROTO).read(), target=TEST_TARGET)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -080099 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700100 self.assertEqual(output, TEST_EXPECTED_OUTPUT)
101
Sapan Bhatia4c835602017-07-14 01:13:17 -0400102 def test_django_with_attic(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700103 """
104 [XOS-GenX] Generate django output from test.xproto
105 """
Zack Williams045b63d2019-01-22 16:30:57 -0700106 args = XOSProcessorArgs(
107 files=[TEST_XPROTO, VROUTER_XPROTO],
108 target="django.xtarget",
109 attic=TEST_ATTICS,
110 output=OUTPUT_DIR,
111 dest_extension="py",
112 write_to_file="model",
113 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800114 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700115
116 # xosmodel has custom header attic
Zack Williams045b63d2019-01-22 16:30:57 -0700117 self.assertIn("from xosmodel_header import *", output["XOSModel"])
118 self.assertIn("class XOSModel(XOSBase):", output["XOSModel"])
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700119
120 # vrouter port use the default header
Zack Williams045b63d2019-01-22 16:30:57 -0700121 self.assertIn("header import *", output["VRouterPort"])
122 self.assertIn("class VRouterPort(XOSBase):", output["VRouterPort"])
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700123
Zack Williams045b63d2019-01-22 16:30:57 -0700124 # verify files
125 xosmodel = OUTPUT_DIR + "/xosmodel.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700126 self.assertTrue(os.path.isfile(xosmodel))
127 xmf = open(xosmodel).read()
Zack Williams045b63d2019-01-22 16:30:57 -0700128 self.assertIn("from xosmodel_header import *", xmf)
129 self.assertIn("class XOSModel(XOSBase):", xmf)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700130
Zack Williams045b63d2019-01-22 16:30:57 -0700131 vrouterport = OUTPUT_DIR + "/vrouterport.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700132 self.assertTrue(os.path.isfile(vrouterport))
133 vrpf = open(vrouterport).read()
Zack Williams045b63d2019-01-22 16:30:57 -0700134 self.assertIn("header import *", vrpf)
135 self.assertIn("class VRouterPort(XOSBase):", vrpf)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700136
Sapan Bhatia4c835602017-07-14 01:13:17 -0400137 def test_django_with_base(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700138 args = XOSProcessorArgs(
139 files=[TEST_XPROTO, BASE_XPROTO],
140 target="django.xtarget",
141 attic=TEST_ATTICS,
142 output=OUTPUT_DIR,
143 dest_extension="py",
144 write_to_file="model",
145 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800146 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700147
148 # verify files
Zack Williams045b63d2019-01-22 16:30:57 -0700149 xosmodel = OUTPUT_DIR + "/xosmodel.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700150 self.assertTrue(os.path.isfile(xosmodel))
151 xmf = open(xosmodel).read()
Zack Williams045b63d2019-01-22 16:30:57 -0700152 self.assertIn("from xosmodel_header import *", xmf)
153 self.assertIn("class XOSModel(XOSBase):", xmf)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700154
Zack Williams045b63d2019-01-22 16:30:57 -0700155 xosbase = OUTPUT_DIR + "/xosbase.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700156 self.assertTrue(os.path.isfile(xosbase))
157 xbf = open(xosbase).read()
Zack Williams045b63d2019-01-22 16:30:57 -0700158 self.assertIn("header import *", xbf)
159 self.assertIn("class XOSBase(models.Model, PlModelMixIn):", xbf)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700160
Sapan Bhatia4c835602017-07-14 01:13:17 -0400161 def test_write_multiple_files(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700162 """
163 [XOS-GenX] read multiple models as input, print one file per model
164 """
Zack Williams045b63d2019-01-22 16:30:57 -0700165 args = XOSProcessorArgs(
166 files=[TEST_XPROTO, VROUTER_XPROTO],
167 target=TEST_TARGET,
168 output=OUTPUT_DIR,
169 dest_extension="txt",
170 write_to_file="model",
171 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800172 XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700173
Zack Williams045b63d2019-01-22 16:30:57 -0700174 generated_files = [f for f in os.listdir(OUTPUT_DIR) if not f.startswith(".")]
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700175 self.assertEqual(len(generated_files), 2)
176
Zack Williams045b63d2019-01-22 16:30:57 -0700177 xosmodel = open(os.path.join(OUTPUT_DIR, "xosmodel.txt"), "r").read()
178 vrouterport = open(os.path.join(OUTPUT_DIR, "vrouterport.txt"), "r").read()
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700179
180 self.assertIn("name: XOSModel", xosmodel)
181 self.assertIn("name: VRouterPort", vrouterport)
182
183 def test_write_multiple_files_from_xtarget(self):
184 """
185 [XOS-GenX] read multiple models as input, print separate files based on +++
186 """
Zack Williams045b63d2019-01-22 16:30:57 -0700187 args = XOSProcessorArgs(
188 files=[TEST_XPROTO, VROUTER_XPROTO],
189 target=SPLIT_TARGET,
190 output=OUTPUT_DIR,
191 write_to_file="target",
192 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800193 XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700194
Zack Williams045b63d2019-01-22 16:30:57 -0700195 generated_files = [f for f in os.listdir(OUTPUT_DIR) if not f.startswith(".")]
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700196 self.assertEqual(len(generated_files), 2)
197
Zack Williams045b63d2019-01-22 16:30:57 -0700198 xosmodel = open(os.path.join(OUTPUT_DIR, "xosmodel.txt"), "r").read()
199 vrouterport = open(os.path.join(OUTPUT_DIR, "vrouterport.txt"), "r").read()
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700200
201 self.assertIn("name: XOSModel", xosmodel)
202 self.assertIn("name: VRouterPort", vrouterport)
203
Sapan Bhatia4c835602017-07-14 01:13:17 -0400204 def test_skip_django(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700205 args = XOSProcessorArgs(
206 files=[SKIP_DJANGO_XPROTO],
207 target="django.xtarget",
208 output=OUTPUT_DIR,
209 dest_extension="py",
210 write_to_file="model",
211 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800212 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700213
214 # should not print a file if options.skip_django = True
Zack Williams045b63d2019-01-22 16:30:57 -0700215 file = OUTPUT_DIR + "/user.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700216 self.assertFalse(os.path.isfile(file))
217
218 def test_service_order(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700219 args = XOSProcessorArgs(
220 files=[BASE_XPROTO, TEST_XPROTO, VROUTER_XPROTO],
221 target="service.xtarget",
222 output=OUTPUT_DIR,
223 write_to_file="target",
224 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800225 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700226
Zack Williams045b63d2019-01-22 16:30:57 -0700227 model = OUTPUT_DIR + "/models.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700228 self.assertTrue(os.path.isfile(model))
229 line_num = 0
230
231 for line in open(model).readlines():
232 line_num += 1
Zack Williams045b63d2019-01-22 16:30:57 -0700233 if line.find("class XOSBase(models.Model, PlModelMixIn):") >= 0:
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700234 base_line = line_num
Zack Williams045b63d2019-01-22 16:30:57 -0700235 if line.find("XOSModel(XOSBase):") >= 0:
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700236 xosmodel_line = line_num
Zack Williams045b63d2019-01-22 16:30:57 -0700237 if line.find("class VRouterPort(XOSBase):") >= 0:
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700238 vrouter_line = line_num
239 self.assertLess(base_line, xosmodel_line)
240 self.assertLess(xosmodel_line, vrouter_line)
241
Scott Baker34dc67e2018-10-02 15:57:50 -0700242 def test_field_numbers(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700243 args = XOSProcessorArgs(files=[FIELDTEST_XPROTO], target=FIELDTEST_TARGET)
Scott Baker34dc67e2018-10-02 15:57:50 -0700244 output = XOSProcessor.process(args)
245
246 def _assert_field(modelname, fieldname, id):
247 self.assertIn("%s,%s,%s" % (modelname, fieldname, id), output)
248
249 _assert_field("Site", "id", 1)
250 _assert_field("Site", "base_field", 2)
251 _assert_field("Site", "base_field2", 3)
252 _assert_field("Site", "otherstuff_field", 102)
253 _assert_field("Site", "slice_field", 201)
254 _assert_field("Site", "slices_ids", 1002)
255
256 _assert_field("Slice", "id", 1)
257 _assert_field("Slice", "base_field", 2)
258 _assert_field("Slice", "base_field2", 3)
259 _assert_field("Slice", "slice_field", 101)
260 _assert_field("Slice", "site", 102)
261
Scott Bakerd87c02a2018-10-29 16:24:29 -0700262 def test_field_numbers(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700263 args = XOSProcessorArgs(
264 files=[REVERSEFIELDTEST_XPROTO], target=FIELDTEST_TARGET
265 )
Scott Bakerd87c02a2018-10-29 16:24:29 -0700266 output = XOSProcessor.process(args)
267
268 def _assert_field(modelname, fieldname, id):
269 self.assertIn("%s,%s,%s" % (modelname, fieldname, id), output)
270
271 # rel_int1s_ids is the reverse link from RelatedToIntermediate1. It gets the related id with no offset, so it
272 # will be assigned 1001. rel_leaf1as_ids inherits from Intermediate1, so its reverse links will all be offset
273 # by 100
274 _assert_field("Leaf1a", "rel_int1s_ids", 1001)
275 _assert_field("Leaf1a", "rel_leaf1as_ids", 1101)
276
277 # rel_int2s_ids is the reverse link from RelatedToIntermediate1. It gets the related id with no offset, so it
278 # will be assigned 1001. rel_leaf1bs_ids inherits from Intermediate1, so its reverse links will all be offset
279 # by 100
280 _assert_field("Leaf1b", "rel_int1s_ids", 1001)
281 _assert_field("Leaf1b", "rel_leaf1bs_ids", 1101)
282
283 # There are no reverse numbers specified for Intermediate2 or Leaf2, so xproto will fall back to automatic
284 # numbering starting at 1900.
285 _assert_field("Leaf2", "rel_int2s_ids", 1900)
286 _assert_field("Leaf2", "rel_leaf2s_ids", 1901)
287
Scott Baker1f7791d2018-10-04 13:21:20 -0700288 def test_unfiltered(self):
289 """ With no include_* args, should get all models """
Zack Williams045b63d2019-01-22 16:30:57 -0700290 args = XOSProcessorArgs(files=[FILTERTEST_XPROTO], target=FILTERTEST_TARGET)
Scott Baker1f7791d2018-10-04 13:21:20 -0700291 output = XOSProcessor.process(args)
292
293 self.assertEqual(output, "Model1,Model2,Model3,")
294
295 def test_filter_models(self):
296 """ Should only get models specified by include_models """
Zack Williams045b63d2019-01-22 16:30:57 -0700297 args = XOSProcessorArgs(
298 files=[FILTERTEST_XPROTO],
299 target=FILTERTEST_TARGET,
300 include_models=["Model1", "Model3"],
301 )
Scott Baker1f7791d2018-10-04 13:21:20 -0700302 output = XOSProcessor.process(args)
303
304 self.assertEqual(output, "Model1,Model3,")
305
306 def test_filter_apps(self):
307 """ Should only get models whose apps are specified by include_apps """
Zack Williams045b63d2019-01-22 16:30:57 -0700308 args = XOSProcessorArgs(
309 files=[FILTERTEST_XPROTO], target=FILTERTEST_TARGET, include_apps=["core"]
310 )
Scott Baker1f7791d2018-10-04 13:21:20 -0700311 output = XOSProcessor.process(args)
312
313 self.assertEqual(output, "Model1,Model2,")
314
315
Zack Williams045b63d2019-01-22 16:30:57 -0700316if __name__ == "__main__":
Sapan Bhatia4c835602017-07-14 01:13:17 -0400317 unittest.main()