blob: b3710cd556894d774fb3ced3bb3016df4b306b01 [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)
Scott Bakerbe2a5172019-04-10 18:02:50 -070048CUSTOM_TEST1_XPROTO = os.path.abspath(
49 os.path.dirname(os.path.realpath(__file__)) + "/xproto/custom_test1.xproto"
50)
51CUSTOM_TEST2_XPROTO = os.path.abspath(
52 os.path.dirname(os.path.realpath(__file__)) + "/xproto/custom_test2.xproto"
53)
Zack Williams045b63d2019-01-22 16:30:57 -070054SKIP_DJANGO_XPROTO = os.path.abspath(
55 os.path.dirname(os.path.realpath(__file__)) + "/xproto/skip_django.xproto"
56)
57VROUTER_XPROTO = os.path.abspath(
58 os.path.dirname(os.path.realpath(__file__)) + "/xproto/vrouterport.xproto"
59)
60TEST_TARGET = os.path.abspath(
61 os.path.dirname(os.path.realpath(__file__)) + "/xtarget/test.xtarget"
62)
63FIELDTEST_TARGET = os.path.abspath(
64 os.path.dirname(os.path.realpath(__file__)) + "/xtarget/fieldtest.xtarget"
65)
66FILTERTEST_TARGET = os.path.abspath(
67 os.path.dirname(os.path.realpath(__file__)) + "/xtarget/filtertest.xtarget"
68)
69SPLIT_TARGET = os.path.abspath(
70 os.path.dirname(os.path.realpath(__file__)) + "/xtarget/split.xtarget"
71)
Matteo Scandolo67654fa2017-06-09 09:33:17 -070072
73TEST_ATTICS = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/attics/")
74
Zack Williams045b63d2019-01-22 16:30:57 -070075
Sapan Bhatiabfb233a2018-02-09 14:53:09 -080076class XOSProcessorTest(unittest.TestCase):
Matteo Scandolo67654fa2017-06-09 09:33:17 -070077 """
78 Testing the XOS Generative Toolchain
79 """
80
81 def setUp(self):
Zack Williams045b63d2019-01-22 16:30:57 -070082 os.chdir(
83 os.path.join(
84 os.path.abspath(os.path.dirname(os.path.realpath(__file__))), ".."
85 )
86 )
Matteo Scandolo67654fa2017-06-09 09:33:17 -070087 filesToRemove = [f for f in os.listdir(OUTPUT_DIR)]
88 for f in filesToRemove:
Zack Williams045b63d2019-01-22 16:30:57 -070089 if not f.startswith("."):
90 os.remove(OUTPUT_DIR + "/" + f)
Matteo Scandolo67654fa2017-06-09 09:33:17 -070091
Sapan Bhatia4c835602017-07-14 01:13:17 -040092 def test_generator_custom_target_from_file(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -070093 """
94 [XOS-GenX] Generate output from base.xproto
95 """
Zack Williams045b63d2019-01-22 16:30:57 -070096 args = XOSProcessorArgs(files=[TEST_XPROTO], target=TEST_TARGET)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -080097 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -070098 self.assertEqual(output, TEST_EXPECTED_OUTPUT)
99
Sapan Bhatia4c835602017-07-14 01:13:17 -0400100 def test_generator_custom_target_from_inputs(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700101 """
102 [XOS-GenX] Generate output from base.xproto
103 """
Zack Williams045b63d2019-01-22 16:30:57 -0700104 args = XOSProcessorArgs(inputs=open(TEST_XPROTO).read(), target=TEST_TARGET)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800105 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700106 self.assertEqual(output, TEST_EXPECTED_OUTPUT)
107
Sapan Bhatia4c835602017-07-14 01:13:17 -0400108 def test_django_with_attic(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700109 """
110 [XOS-GenX] Generate django output from test.xproto
111 """
Zack Williams045b63d2019-01-22 16:30:57 -0700112 args = XOSProcessorArgs(
113 files=[TEST_XPROTO, VROUTER_XPROTO],
114 target="django.xtarget",
115 attic=TEST_ATTICS,
116 output=OUTPUT_DIR,
117 dest_extension="py",
118 write_to_file="model",
119 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800120 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700121
122 # xosmodel has custom header attic
Scott Bakerbe2a5172019-04-10 18:02:50 -0700123 self.assertIn("from core.models.xosbase import *", output["XOSModel"])
124 self.assertIn("class XOSModel_decl(XOSBase):", output["XOSModel"])
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700125
126 # vrouter port use the default header
Scott Bakerbe2a5172019-04-10 18:02:50 -0700127 self.assertIn("from core.models.xosbase import *", output["VRouterPort"])
128 self.assertIn("class VRouterPort_decl(XOSBase):", output["VRouterPort"])
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700129
Zack Williams045b63d2019-01-22 16:30:57 -0700130 # verify files
131 xosmodel = OUTPUT_DIR + "/xosmodel.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700132 self.assertTrue(os.path.isfile(xosmodel))
133 xmf = open(xosmodel).read()
Scott Bakerbe2a5172019-04-10 18:02:50 -0700134 self.assertIn("from core.models.xosbase import *", xmf)
135 self.assertIn("class XOSModel_decl(XOSBase):", xmf)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700136
Zack Williams045b63d2019-01-22 16:30:57 -0700137 vrouterport = OUTPUT_DIR + "/vrouterport.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700138 self.assertTrue(os.path.isfile(vrouterport))
139 vrpf = open(vrouterport).read()
Scott Bakerbe2a5172019-04-10 18:02:50 -0700140 self.assertIn("from core.models.xosbase import *", vrpf)
141 self.assertIn("class VRouterPort_decl(XOSBase):", vrpf)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700142
Sapan Bhatia4c835602017-07-14 01:13:17 -0400143 def test_django_with_base(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700144 args = XOSProcessorArgs(
145 files=[TEST_XPROTO, BASE_XPROTO],
146 target="django.xtarget",
147 attic=TEST_ATTICS,
148 output=OUTPUT_DIR,
149 dest_extension="py",
150 write_to_file="model",
151 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800152 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700153
154 # verify files
Zack Williams045b63d2019-01-22 16:30:57 -0700155 xosmodel = OUTPUT_DIR + "/xosmodel.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700156 self.assertTrue(os.path.isfile(xosmodel))
157 xmf = open(xosmodel).read()
Scott Bakerbe2a5172019-04-10 18:02:50 -0700158 self.assertIn("from core.models.xosbase import *", xmf)
159 self.assertIn("class XOSModel_decl(XOSBase):", xmf)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700160
Zack Williams045b63d2019-01-22 16:30:57 -0700161 xosbase = OUTPUT_DIR + "/xosbase.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700162 self.assertTrue(os.path.isfile(xosbase))
163 xbf = open(xosbase).read()
Scott Bakerbe2a5172019-04-10 18:02:50 -0700164 self.assertIn("from core.models.xosbase import *", xbf)
165 self.assertIn("class XOSBase_decl(models.Model, PlModelMixIn):", xbf)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700166
Sapan Bhatia4c835602017-07-14 01:13:17 -0400167 def test_write_multiple_files(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700168 """
169 [XOS-GenX] read multiple models as input, print one file per model
170 """
Zack Williams045b63d2019-01-22 16:30:57 -0700171 args = XOSProcessorArgs(
172 files=[TEST_XPROTO, VROUTER_XPROTO],
173 target=TEST_TARGET,
174 output=OUTPUT_DIR,
175 dest_extension="txt",
176 write_to_file="model",
177 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800178 XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700179
Zack Williams045b63d2019-01-22 16:30:57 -0700180 generated_files = [f for f in os.listdir(OUTPUT_DIR) if not f.startswith(".")]
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700181 self.assertEqual(len(generated_files), 2)
182
Zack Williams045b63d2019-01-22 16:30:57 -0700183 xosmodel = open(os.path.join(OUTPUT_DIR, "xosmodel.txt"), "r").read()
184 vrouterport = open(os.path.join(OUTPUT_DIR, "vrouterport.txt"), "r").read()
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700185
186 self.assertIn("name: XOSModel", xosmodel)
187 self.assertIn("name: VRouterPort", vrouterport)
188
189 def test_write_multiple_files_from_xtarget(self):
190 """
191 [XOS-GenX] read multiple models as input, print separate files based on +++
192 """
Zack Williams045b63d2019-01-22 16:30:57 -0700193 args = XOSProcessorArgs(
194 files=[TEST_XPROTO, VROUTER_XPROTO],
195 target=SPLIT_TARGET,
196 output=OUTPUT_DIR,
197 write_to_file="target",
198 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800199 XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700200
Zack Williams045b63d2019-01-22 16:30:57 -0700201 generated_files = [f for f in os.listdir(OUTPUT_DIR) if not f.startswith(".")]
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700202 self.assertEqual(len(generated_files), 2)
203
Zack Williams045b63d2019-01-22 16:30:57 -0700204 xosmodel = open(os.path.join(OUTPUT_DIR, "xosmodel.txt"), "r").read()
205 vrouterport = open(os.path.join(OUTPUT_DIR, "vrouterport.txt"), "r").read()
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700206
207 self.assertIn("name: XOSModel", xosmodel)
208 self.assertIn("name: VRouterPort", vrouterport)
209
Sapan Bhatia4c835602017-07-14 01:13:17 -0400210 def test_skip_django(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700211 args = XOSProcessorArgs(
212 files=[SKIP_DJANGO_XPROTO],
213 target="django.xtarget",
214 output=OUTPUT_DIR,
215 dest_extension="py",
216 write_to_file="model",
217 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800218 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700219
220 # should not print a file if options.skip_django = True
Zack Williams045b63d2019-01-22 16:30:57 -0700221 file = OUTPUT_DIR + "/user.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700222 self.assertFalse(os.path.isfile(file))
223
224 def test_service_order(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700225 args = XOSProcessorArgs(
226 files=[BASE_XPROTO, TEST_XPROTO, VROUTER_XPROTO],
227 target="service.xtarget",
228 output=OUTPUT_DIR,
229 write_to_file="target",
230 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800231 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700232
Zack Williams045b63d2019-01-22 16:30:57 -0700233 model = OUTPUT_DIR + "/models.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700234 self.assertTrue(os.path.isfile(model))
235 line_num = 0
236
237 for line in open(model).readlines():
238 line_num += 1
Zack Williams045b63d2019-01-22 16:30:57 -0700239 if line.find("class XOSBase(models.Model, PlModelMixIn):") >= 0:
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700240 base_line = line_num
Zack Williams045b63d2019-01-22 16:30:57 -0700241 if line.find("XOSModel(XOSBase):") >= 0:
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700242 xosmodel_line = line_num
Zack Williams045b63d2019-01-22 16:30:57 -0700243 if line.find("class VRouterPort(XOSBase):") >= 0:
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700244 vrouter_line = line_num
245 self.assertLess(base_line, xosmodel_line)
246 self.assertLess(xosmodel_line, vrouter_line)
247
Scott Baker34dc67e2018-10-02 15:57:50 -0700248 def test_field_numbers(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700249 args = XOSProcessorArgs(files=[FIELDTEST_XPROTO], target=FIELDTEST_TARGET)
Scott Baker34dc67e2018-10-02 15:57:50 -0700250 output = XOSProcessor.process(args)
251
252 def _assert_field(modelname, fieldname, id):
253 self.assertIn("%s,%s,%s" % (modelname, fieldname, id), output)
254
255 _assert_field("Site", "id", 1)
256 _assert_field("Site", "base_field", 2)
257 _assert_field("Site", "base_field2", 3)
258 _assert_field("Site", "otherstuff_field", 102)
259 _assert_field("Site", "slice_field", 201)
260 _assert_field("Site", "slices_ids", 1002)
261
262 _assert_field("Slice", "id", 1)
263 _assert_field("Slice", "base_field", 2)
264 _assert_field("Slice", "base_field2", 3)
265 _assert_field("Slice", "slice_field", 101)
266 _assert_field("Slice", "site", 102)
267
Scott Bakerd87c02a2018-10-29 16:24:29 -0700268 def test_field_numbers(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700269 args = XOSProcessorArgs(
270 files=[REVERSEFIELDTEST_XPROTO], target=FIELDTEST_TARGET
271 )
Scott Bakerd87c02a2018-10-29 16:24:29 -0700272 output = XOSProcessor.process(args)
273
274 def _assert_field(modelname, fieldname, id):
275 self.assertIn("%s,%s,%s" % (modelname, fieldname, id), output)
276
277 # rel_int1s_ids is the reverse link from RelatedToIntermediate1. It gets the related id with no offset, so it
278 # will be assigned 1001. rel_leaf1as_ids inherits from Intermediate1, so its reverse links will all be offset
279 # by 100
280 _assert_field("Leaf1a", "rel_int1s_ids", 1001)
281 _assert_field("Leaf1a", "rel_leaf1as_ids", 1101)
282
283 # rel_int2s_ids is the reverse link from RelatedToIntermediate1. It gets the related id with no offset, so it
284 # will be assigned 1001. rel_leaf1bs_ids inherits from Intermediate1, so its reverse links will all be offset
285 # by 100
286 _assert_field("Leaf1b", "rel_int1s_ids", 1001)
287 _assert_field("Leaf1b", "rel_leaf1bs_ids", 1101)
288
289 # There are no reverse numbers specified for Intermediate2 or Leaf2, so xproto will fall back to automatic
290 # numbering starting at 1900.
291 _assert_field("Leaf2", "rel_int2s_ids", 1900)
292 _assert_field("Leaf2", "rel_leaf2s_ids", 1901)
293
Scott Baker1f7791d2018-10-04 13:21:20 -0700294 def test_unfiltered(self):
295 """ With no include_* args, should get all models """
Zack Williams045b63d2019-01-22 16:30:57 -0700296 args = XOSProcessorArgs(files=[FILTERTEST_XPROTO], target=FILTERTEST_TARGET)
Scott Baker1f7791d2018-10-04 13:21:20 -0700297 output = XOSProcessor.process(args)
298
299 self.assertEqual(output, "Model1,Model2,Model3,")
300
301 def test_filter_models(self):
302 """ Should only get models specified by include_models """
Zack Williams045b63d2019-01-22 16:30:57 -0700303 args = XOSProcessorArgs(
304 files=[FILTERTEST_XPROTO],
305 target=FILTERTEST_TARGET,
306 include_models=["Model1", "Model3"],
307 )
Scott Baker1f7791d2018-10-04 13:21:20 -0700308 output = XOSProcessor.process(args)
309
310 self.assertEqual(output, "Model1,Model3,")
311
312 def test_filter_apps(self):
313 """ Should only get models whose apps are specified by include_apps """
Zack Williams045b63d2019-01-22 16:30:57 -0700314 args = XOSProcessorArgs(
315 files=[FILTERTEST_XPROTO], target=FILTERTEST_TARGET, include_apps=["core"]
316 )
Scott Baker1f7791d2018-10-04 13:21:20 -0700317 output = XOSProcessor.process(args)
318
319 self.assertEqual(output, "Model1,Model2,")
320
Scott Bakerbe2a5172019-04-10 18:02:50 -0700321 def test_django_custom_test1(self):
322 args = XOSProcessorArgs(
323 files=[CUSTOM_TEST1_XPROTO, BASE_XPROTO],
324 target="django.xtarget",
325 attic=TEST_ATTICS,
326 output=OUTPUT_DIR,
327 dest_extension="py",
328 write_to_file="model",
329 )
330 output = XOSProcessor.process(args)
331
332 # verify files
333 xosmodel = OUTPUT_DIR + "/xosmodel_decl.py"
334 self.assertTrue(os.path.isfile(xosmodel))
335 xmf = open(xosmodel).read()
336 self.assertIn("class XOSModel_decl(XOSBase):", xmf)
337
338 xosmodel = OUTPUT_DIR + "/xosmodel2_decl.py"
339 self.assertTrue(os.path.isfile(xosmodel))
340 xmf = open(xosmodel).read()
341 self.assertIn("class XOSModel2_decl(XOSBase):", xmf)
342
343 def test_django_custom_test2(self):
344 args = XOSProcessorArgs(
345 files=[CUSTOM_TEST2_XPROTO, BASE_XPROTO],
346 target="django.xtarget",
347 attic=TEST_ATTICS,
348 output=OUTPUT_DIR,
349 dest_extension="py",
350 write_to_file="model",
351 )
352 output = XOSProcessor.process(args)
353
354 # verify files
355 xosmodel = OUTPUT_DIR + "/xosmodel_decl.py"
356 self.assertTrue(os.path.isfile(xosmodel))
357 xmf = open(xosmodel).read()
358 self.assertIn("class XOSModel_decl(XOSBase):", xmf)
359 self.assertNotIn("class XOSModel(XOSModel_decl):", xmf)
360
361 xosmodel = OUTPUT_DIR + "/xosmodel2.py"
362 self.assertTrue(os.path.isfile(xosmodel))
363 xmf = open(xosmodel).read()
364 self.assertIn("class XOSModel2_decl(XOSBase):", xmf)
365 self.assertIn("class XOSModel2(XOSModel2_decl):", xmf)
366
367 def test_service_custom_test1(self):
368 args = XOSProcessorArgs(
369 files=[CUSTOM_TEST1_XPROTO, BASE_XPROTO],
370 target="service.xtarget",
371 attic=TEST_ATTICS,
372 output=OUTPUT_DIR,
373 dest_extension="py",
374 write_to_file="target",
375 )
376 output = XOSProcessor.process(args)
377
378 # verify files
379 xosmodel = OUTPUT_DIR + "/models_decl.py"
380 self.assertTrue(os.path.isfile(xosmodel))
381 xmf = open(xosmodel).read()
382 self.assertIn("class XOSModel_decl(XOSBase_decl):", xmf)
383
384 xosmodel = OUTPUT_DIR + "/models_decl.py"
385 self.assertTrue(os.path.isfile(xosmodel))
386 xmf = open(xosmodel).read()
387 self.assertIn("class XOSModel2_decl(XOSBase_decl):", xmf)
388
Scott Baker1f7791d2018-10-04 13:21:20 -0700389
Zack Williams045b63d2019-01-22 16:30:57 -0700390if __name__ == "__main__":
Sapan Bhatia4c835602017-07-14 01:13:17 -0400391 unittest.main()