blob: 1de6bd8fd1eeecc7a71e477d75bf2d250155227e [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
Matteo Scandolo67654fa2017-06-09 09:33:17 -070016import unittest
17import os
Scott Baker1f7791d2018-10-04 13:21:20 -070018from helpers import OUTPUT_DIR
19from xosgenx.generator import XOSProcessor, XOSProcessorArgs
Matteo Scandolo67654fa2017-06-09 09:33:17 -070020
21TEST_EXPECTED_OUTPUT = """
22 name: XOSModel
23 fields:
24 name:
25 type: string
26 description: "Help Name"
27 files:
28 type: string
29 description: "Help Files"
30"""
31
Zack Williams045b63d2019-01-22 16:30:57 -070032BASE_XPROTO = os.path.abspath(
33 os.path.dirname(os.path.realpath(__file__)) + "/xproto/base.xproto"
34)
35TEST_XPROTO = os.path.abspath(
36 os.path.dirname(os.path.realpath(__file__)) + "/xproto/test.xproto"
37)
38FIELDTEST_XPROTO = os.path.abspath(
39 os.path.dirname(os.path.realpath(__file__)) + "/xproto/fieldtest.xproto"
40)
41REVERSEFIELDTEST_XPROTO = os.path.abspath(
42 os.path.dirname(os.path.realpath(__file__)) + "/xproto/reversefieldtest.xproto"
43)
44FILTERTEST_XPROTO = os.path.abspath(
45 os.path.dirname(os.path.realpath(__file__)) + "/xproto/filtertest.xproto"
46)
47SKIP_DJANGO_XPROTO = os.path.abspath(
48 os.path.dirname(os.path.realpath(__file__)) + "/xproto/skip_django.xproto"
49)
50VROUTER_XPROTO = os.path.abspath(
51 os.path.dirname(os.path.realpath(__file__)) + "/xproto/vrouterport.xproto"
52)
53TEST_TARGET = os.path.abspath(
54 os.path.dirname(os.path.realpath(__file__)) + "/xtarget/test.xtarget"
55)
56FIELDTEST_TARGET = os.path.abspath(
57 os.path.dirname(os.path.realpath(__file__)) + "/xtarget/fieldtest.xtarget"
58)
59FILTERTEST_TARGET = os.path.abspath(
60 os.path.dirname(os.path.realpath(__file__)) + "/xtarget/filtertest.xtarget"
61)
62SPLIT_TARGET = os.path.abspath(
63 os.path.dirname(os.path.realpath(__file__)) + "/xtarget/split.xtarget"
64)
Matteo Scandolo67654fa2017-06-09 09:33:17 -070065
66TEST_ATTICS = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/attics/")
67
Zack Williams045b63d2019-01-22 16:30:57 -070068
Sapan Bhatiabfb233a2018-02-09 14:53:09 -080069class XOSProcessorTest(unittest.TestCase):
Matteo Scandolo67654fa2017-06-09 09:33:17 -070070 """
71 Testing the XOS Generative Toolchain
72 """
73
74 def setUp(self):
Zack Williams045b63d2019-01-22 16:30:57 -070075 os.chdir(
76 os.path.join(
77 os.path.abspath(os.path.dirname(os.path.realpath(__file__))), ".."
78 )
79 )
Matteo Scandolo67654fa2017-06-09 09:33:17 -070080 filesToRemove = [f for f in os.listdir(OUTPUT_DIR)]
81 for f in filesToRemove:
Zack Williams045b63d2019-01-22 16:30:57 -070082 if not f.startswith("."):
83 os.remove(OUTPUT_DIR + "/" + f)
Matteo Scandolo67654fa2017-06-09 09:33:17 -070084
Sapan Bhatia4c835602017-07-14 01:13:17 -040085 def test_generator_custom_target_from_file(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -070086 """
87 [XOS-GenX] Generate output from base.xproto
88 """
Zack Williams045b63d2019-01-22 16:30:57 -070089 args = XOSProcessorArgs(files=[TEST_XPROTO], target=TEST_TARGET)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -080090 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -070091 self.assertEqual(output, TEST_EXPECTED_OUTPUT)
92
Sapan Bhatia4c835602017-07-14 01:13:17 -040093 def test_generator_custom_target_from_inputs(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -070094 """
95 [XOS-GenX] Generate output from base.xproto
96 """
Zack Williams045b63d2019-01-22 16:30:57 -070097 args = XOSProcessorArgs(inputs=open(TEST_XPROTO).read(), target=TEST_TARGET)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -080098 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -070099 self.assertEqual(output, TEST_EXPECTED_OUTPUT)
100
Sapan Bhatia4c835602017-07-14 01:13:17 -0400101 def test_django_with_attic(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700102 """
103 [XOS-GenX] Generate django output from test.xproto
104 """
Zack Williams045b63d2019-01-22 16:30:57 -0700105 args = XOSProcessorArgs(
106 files=[TEST_XPROTO, VROUTER_XPROTO],
107 target="django.xtarget",
108 attic=TEST_ATTICS,
109 output=OUTPUT_DIR,
110 dest_extension="py",
111 write_to_file="model",
112 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800113 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700114
115 # xosmodel has custom header attic
Zack Williams045b63d2019-01-22 16:30:57 -0700116 self.assertIn("from xosmodel_header import *", output["XOSModel"])
117 self.assertIn("class XOSModel(XOSBase):", output["XOSModel"])
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700118
119 # vrouter port use the default header
Zack Williams045b63d2019-01-22 16:30:57 -0700120 self.assertIn("header import *", output["VRouterPort"])
121 self.assertIn("class VRouterPort(XOSBase):", output["VRouterPort"])
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700122
Zack Williams045b63d2019-01-22 16:30:57 -0700123 # verify files
124 xosmodel = OUTPUT_DIR + "/xosmodel.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700125 self.assertTrue(os.path.isfile(xosmodel))
126 xmf = open(xosmodel).read()
Zack Williams045b63d2019-01-22 16:30:57 -0700127 self.assertIn("from xosmodel_header import *", xmf)
128 self.assertIn("class XOSModel(XOSBase):", xmf)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700129
Zack Williams045b63d2019-01-22 16:30:57 -0700130 vrouterport = OUTPUT_DIR + "/vrouterport.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700131 self.assertTrue(os.path.isfile(vrouterport))
132 vrpf = open(vrouterport).read()
Zack Williams045b63d2019-01-22 16:30:57 -0700133 self.assertIn("header import *", vrpf)
134 self.assertIn("class VRouterPort(XOSBase):", vrpf)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700135
Sapan Bhatia4c835602017-07-14 01:13:17 -0400136 def test_django_with_base(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700137 args = XOSProcessorArgs(
138 files=[TEST_XPROTO, BASE_XPROTO],
139 target="django.xtarget",
140 attic=TEST_ATTICS,
141 output=OUTPUT_DIR,
142 dest_extension="py",
143 write_to_file="model",
144 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800145 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700146
147 # verify files
Zack Williams045b63d2019-01-22 16:30:57 -0700148 xosmodel = OUTPUT_DIR + "/xosmodel.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700149 self.assertTrue(os.path.isfile(xosmodel))
150 xmf = open(xosmodel).read()
Zack Williams045b63d2019-01-22 16:30:57 -0700151 self.assertIn("from xosmodel_header import *", xmf)
152 self.assertIn("class XOSModel(XOSBase):", xmf)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700153
Zack Williams045b63d2019-01-22 16:30:57 -0700154 xosbase = OUTPUT_DIR + "/xosbase.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700155 self.assertTrue(os.path.isfile(xosbase))
156 xbf = open(xosbase).read()
Zack Williams045b63d2019-01-22 16:30:57 -0700157 self.assertIn("header import *", xbf)
158 self.assertIn("class XOSBase(models.Model, PlModelMixIn):", xbf)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700159
Sapan Bhatia4c835602017-07-14 01:13:17 -0400160 def test_write_multiple_files(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700161 """
162 [XOS-GenX] read multiple models as input, print one file per model
163 """
Zack Williams045b63d2019-01-22 16:30:57 -0700164 args = XOSProcessorArgs(
165 files=[TEST_XPROTO, VROUTER_XPROTO],
166 target=TEST_TARGET,
167 output=OUTPUT_DIR,
168 dest_extension="txt",
169 write_to_file="model",
170 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800171 XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700172
Zack Williams045b63d2019-01-22 16:30:57 -0700173 generated_files = [f for f in os.listdir(OUTPUT_DIR) if not f.startswith(".")]
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700174 self.assertEqual(len(generated_files), 2)
175
Zack Williams045b63d2019-01-22 16:30:57 -0700176 xosmodel = open(os.path.join(OUTPUT_DIR, "xosmodel.txt"), "r").read()
177 vrouterport = open(os.path.join(OUTPUT_DIR, "vrouterport.txt"), "r").read()
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700178
179 self.assertIn("name: XOSModel", xosmodel)
180 self.assertIn("name: VRouterPort", vrouterport)
181
182 def test_write_multiple_files_from_xtarget(self):
183 """
184 [XOS-GenX] read multiple models as input, print separate files based on +++
185 """
Zack Williams045b63d2019-01-22 16:30:57 -0700186 args = XOSProcessorArgs(
187 files=[TEST_XPROTO, VROUTER_XPROTO],
188 target=SPLIT_TARGET,
189 output=OUTPUT_DIR,
190 write_to_file="target",
191 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800192 XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700193
Zack Williams045b63d2019-01-22 16:30:57 -0700194 generated_files = [f for f in os.listdir(OUTPUT_DIR) if not f.startswith(".")]
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700195 self.assertEqual(len(generated_files), 2)
196
Zack Williams045b63d2019-01-22 16:30:57 -0700197 xosmodel = open(os.path.join(OUTPUT_DIR, "xosmodel.txt"), "r").read()
198 vrouterport = open(os.path.join(OUTPUT_DIR, "vrouterport.txt"), "r").read()
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700199
200 self.assertIn("name: XOSModel", xosmodel)
201 self.assertIn("name: VRouterPort", vrouterport)
202
Sapan Bhatia4c835602017-07-14 01:13:17 -0400203 def test_skip_django(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700204 args = XOSProcessorArgs(
205 files=[SKIP_DJANGO_XPROTO],
206 target="django.xtarget",
207 output=OUTPUT_DIR,
208 dest_extension="py",
209 write_to_file="model",
210 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800211 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700212
213 # should not print a file if options.skip_django = True
Zack Williams045b63d2019-01-22 16:30:57 -0700214 file = OUTPUT_DIR + "/user.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700215 self.assertFalse(os.path.isfile(file))
216
217 def test_service_order(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700218 args = XOSProcessorArgs(
219 files=[BASE_XPROTO, TEST_XPROTO, VROUTER_XPROTO],
220 target="service.xtarget",
221 output=OUTPUT_DIR,
222 write_to_file="target",
223 )
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800224 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700225
Zack Williams045b63d2019-01-22 16:30:57 -0700226 model = OUTPUT_DIR + "/models.py"
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700227 self.assertTrue(os.path.isfile(model))
228 line_num = 0
229
230 for line in open(model).readlines():
231 line_num += 1
Zack Williams045b63d2019-01-22 16:30:57 -0700232 if line.find("class XOSBase(models.Model, PlModelMixIn):") >= 0:
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700233 base_line = line_num
Zack Williams045b63d2019-01-22 16:30:57 -0700234 if line.find("XOSModel(XOSBase):") >= 0:
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700235 xosmodel_line = line_num
Zack Williams045b63d2019-01-22 16:30:57 -0700236 if line.find("class VRouterPort(XOSBase):") >= 0:
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700237 vrouter_line = line_num
238 self.assertLess(base_line, xosmodel_line)
239 self.assertLess(xosmodel_line, vrouter_line)
240
Scott Baker34dc67e2018-10-02 15:57:50 -0700241 def test_field_numbers(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700242 args = XOSProcessorArgs(files=[FIELDTEST_XPROTO], target=FIELDTEST_TARGET)
Scott Baker34dc67e2018-10-02 15:57:50 -0700243 output = XOSProcessor.process(args)
244
245 def _assert_field(modelname, fieldname, id):
246 self.assertIn("%s,%s,%s" % (modelname, fieldname, id), output)
247
248 _assert_field("Site", "id", 1)
249 _assert_field("Site", "base_field", 2)
250 _assert_field("Site", "base_field2", 3)
251 _assert_field("Site", "otherstuff_field", 102)
252 _assert_field("Site", "slice_field", 201)
253 _assert_field("Site", "slices_ids", 1002)
254
255 _assert_field("Slice", "id", 1)
256 _assert_field("Slice", "base_field", 2)
257 _assert_field("Slice", "base_field2", 3)
258 _assert_field("Slice", "slice_field", 101)
259 _assert_field("Slice", "site", 102)
260
Scott Bakerd87c02a2018-10-29 16:24:29 -0700261 def test_field_numbers(self):
Zack Williams045b63d2019-01-22 16:30:57 -0700262 args = XOSProcessorArgs(
263 files=[REVERSEFIELDTEST_XPROTO], target=FIELDTEST_TARGET
264 )
Scott Bakerd87c02a2018-10-29 16:24:29 -0700265 output = XOSProcessor.process(args)
266
267 def _assert_field(modelname, fieldname, id):
268 self.assertIn("%s,%s,%s" % (modelname, fieldname, id), output)
269
270 # rel_int1s_ids is the reverse link from RelatedToIntermediate1. It gets the related id with no offset, so it
271 # will be assigned 1001. rel_leaf1as_ids inherits from Intermediate1, so its reverse links will all be offset
272 # by 100
273 _assert_field("Leaf1a", "rel_int1s_ids", 1001)
274 _assert_field("Leaf1a", "rel_leaf1as_ids", 1101)
275
276 # rel_int2s_ids is the reverse link from RelatedToIntermediate1. It gets the related id with no offset, so it
277 # will be assigned 1001. rel_leaf1bs_ids inherits from Intermediate1, so its reverse links will all be offset
278 # by 100
279 _assert_field("Leaf1b", "rel_int1s_ids", 1001)
280 _assert_field("Leaf1b", "rel_leaf1bs_ids", 1101)
281
282 # There are no reverse numbers specified for Intermediate2 or Leaf2, so xproto will fall back to automatic
283 # numbering starting at 1900.
284 _assert_field("Leaf2", "rel_int2s_ids", 1900)
285 _assert_field("Leaf2", "rel_leaf2s_ids", 1901)
286
Scott Baker1f7791d2018-10-04 13:21:20 -0700287 def test_unfiltered(self):
288 """ With no include_* args, should get all models """
Zack Williams045b63d2019-01-22 16:30:57 -0700289 args = XOSProcessorArgs(files=[FILTERTEST_XPROTO], target=FILTERTEST_TARGET)
Scott Baker1f7791d2018-10-04 13:21:20 -0700290 output = XOSProcessor.process(args)
291
292 self.assertEqual(output, "Model1,Model2,Model3,")
293
294 def test_filter_models(self):
295 """ Should only get models specified by include_models """
Zack Williams045b63d2019-01-22 16:30:57 -0700296 args = XOSProcessorArgs(
297 files=[FILTERTEST_XPROTO],
298 target=FILTERTEST_TARGET,
299 include_models=["Model1", "Model3"],
300 )
Scott Baker1f7791d2018-10-04 13:21:20 -0700301 output = XOSProcessor.process(args)
302
303 self.assertEqual(output, "Model1,Model3,")
304
305 def test_filter_apps(self):
306 """ Should only get models whose apps are specified by include_apps """
Zack Williams045b63d2019-01-22 16:30:57 -0700307 args = XOSProcessorArgs(
308 files=[FILTERTEST_XPROTO], target=FILTERTEST_TARGET, include_apps=["core"]
309 )
Scott Baker1f7791d2018-10-04 13:21:20 -0700310 output = XOSProcessor.process(args)
311
312 self.assertEqual(output, "Model1,Model2,")
313
314
Zack Williams045b63d2019-01-22 16:30:57 -0700315if __name__ == "__main__":
Sapan Bhatia4c835602017-07-14 01:13:17 -0400316 unittest.main()