blob: 3daa5949bbc68fc12ace14c1cb56dff06cf08741 [file] [log] [blame]
Matteo Scandolod2044a42017-08-07 16:08:28 -07001
2# Copyright 2017-present Open Networking Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
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
33BASE_XPROTO = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xproto/base.xproto")
34TEST_XPROTO = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xproto/test.xproto")
Scott Baker34dc67e2018-10-02 15:57:50 -070035FIELDTEST_XPROTO = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xproto/fieldtest.xproto")
Scott Bakerd87c02a2018-10-29 16:24:29 -070036REVERSEFIELDTEST_XPROTO = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xproto/reversefieldtest.xproto")
Scott Baker1f7791d2018-10-04 13:21:20 -070037FILTERTEST_XPROTO = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xproto/filtertest.xproto")
Matteo Scandolo67654fa2017-06-09 09:33:17 -070038SKIP_DJANGO_XPROTO = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xproto/skip_django.xproto")
39VROUTER_XPROTO = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xproto/vrouterport.xproto")
40TEST_TARGET = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xtarget/test.xtarget")
Scott Baker34dc67e2018-10-02 15:57:50 -070041FIELDTEST_TARGET = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xtarget/fieldtest.xtarget")
Scott Baker1f7791d2018-10-04 13:21:20 -070042FILTERTEST_TARGET = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xtarget/filtertest.xtarget")
Matteo Scandolo67654fa2017-06-09 09:33:17 -070043SPLIT_TARGET = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/xtarget/split.xtarget")
44
45TEST_ATTICS = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/attics/")
46
Sapan Bhatiabfb233a2018-02-09 14:53:09 -080047class XOSProcessorTest(unittest.TestCase):
Matteo Scandolo67654fa2017-06-09 09:33:17 -070048 """
49 Testing the XOS Generative Toolchain
50 """
51
52 def setUp(self):
Scott Baker7dddd512017-10-24 10:13:34 -070053 os.chdir(os.path.join(os.path.abspath(os.path.dirname(os.path.realpath(__file__))), ".."))
Matteo Scandolo67654fa2017-06-09 09:33:17 -070054 filesToRemove = [f for f in os.listdir(OUTPUT_DIR)]
55 for f in filesToRemove:
56 if not f.startswith('.'):
57 os.remove(OUTPUT_DIR + '/' + f)
58
Sapan Bhatia4c835602017-07-14 01:13:17 -040059 def test_generator_custom_target_from_file(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -070060 """
61 [XOS-GenX] Generate output from base.xproto
62 """
Scott Baker1f7791d2018-10-04 13:21:20 -070063 args = XOSProcessorArgs(files = [TEST_XPROTO],
64 target = TEST_TARGET)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -080065 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -070066 self.assertEqual(output, TEST_EXPECTED_OUTPUT)
67
Sapan Bhatia4c835602017-07-14 01:13:17 -040068 def test_generator_custom_target_from_inputs(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -070069 """
70 [XOS-GenX] Generate output from base.xproto
71 """
Scott Baker1f7791d2018-10-04 13:21:20 -070072 args = XOSProcessorArgs(inputs = open(TEST_XPROTO).read(),
73 target = TEST_TARGET)
Sapan Bhatiabfb233a2018-02-09 14:53:09 -080074 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -070075 self.assertEqual(output, TEST_EXPECTED_OUTPUT)
76
Sapan Bhatia4c835602017-07-14 01:13:17 -040077 def test_django_with_attic(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -070078 """
79 [XOS-GenX] Generate django output from test.xproto
80 """
Scott Baker1f7791d2018-10-04 13:21:20 -070081 args = XOSProcessorArgs(files = [TEST_XPROTO, VROUTER_XPROTO],
82 target = 'django.xtarget',
83 attic = TEST_ATTICS,
84 output = OUTPUT_DIR,
85 dest_extension = 'py',
86 write_to_file = 'model')
Sapan Bhatiabfb233a2018-02-09 14:53:09 -080087 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -070088
89 # xosmodel has custom header attic
90 self.assertIn('from xosmodel_header import *', output['XOSModel'])
91 self.assertIn('class XOSModel(XOSBase):', output['XOSModel'])
92
93 # vrouter port use the default header
94 self.assertIn('header import *', output['VRouterPort'])
95 self.assertIn('class VRouterPort(XOSBase):', output['VRouterPort'])
96
97 #verify files
98 xosmodel = OUTPUT_DIR + '/xosmodel.py'
99 self.assertTrue(os.path.isfile(xosmodel))
100 xmf = open(xosmodel).read()
101 self.assertIn('from xosmodel_header import *', xmf)
102 self.assertIn('class XOSModel(XOSBase):', xmf)
103
104 vrouterport = OUTPUT_DIR + '/vrouterport.py'
105 self.assertTrue(os.path.isfile(vrouterport))
106 vrpf = open(vrouterport).read()
107 self.assertIn('header import *', vrpf)
108 self.assertIn('class VRouterPort(XOSBase):', vrpf)
109
Sapan Bhatia4c835602017-07-14 01:13:17 -0400110 def test_django_with_base(self):
Scott Baker1f7791d2018-10-04 13:21:20 -0700111 args = XOSProcessorArgs(files = [TEST_XPROTO, BASE_XPROTO],
112 target = 'django.xtarget',
113 attic = TEST_ATTICS,
114 output = OUTPUT_DIR,
115 dest_extension = 'py',
116 write_to_file = 'model')
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800117 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700118
119 # verify files
120 xosmodel = OUTPUT_DIR + '/xosmodel.py'
121 self.assertTrue(os.path.isfile(xosmodel))
122 xmf = open(xosmodel).read()
123 self.assertIn('from xosmodel_header import *', xmf)
124 self.assertIn('class XOSModel(XOSBase):', xmf)
125
126 xosbase = OUTPUT_DIR + '/xosbase.py'
127 self.assertTrue(os.path.isfile(xosbase))
128 xbf = open(xosbase).read()
129 self.assertIn('header import *', xbf)
130 self.assertIn('class XOSBase(models.Model, PlModelMixIn):', xbf)
131
Sapan Bhatia4c835602017-07-14 01:13:17 -0400132 def test_write_multiple_files(self):
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700133 """
134 [XOS-GenX] read multiple models as input, print one file per model
135 """
Scott Baker1f7791d2018-10-04 13:21:20 -0700136 args = XOSProcessorArgs(files = [TEST_XPROTO, VROUTER_XPROTO],
137 target = TEST_TARGET,
138 output = OUTPUT_DIR,
139 dest_extension = 'txt',
140 write_to_file = 'model')
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800141 XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700142
143 generated_files = [f for f in os.listdir(OUTPUT_DIR) if not f.startswith('.')]
144 self.assertEqual(len(generated_files), 2)
145
146 xosmodel = open(os.path.join(OUTPUT_DIR, 'xosmodel.txt'), "r").read()
147 vrouterport = open(os.path.join(OUTPUT_DIR, 'vrouterport.txt'), "r").read()
148
149 self.assertIn("name: XOSModel", xosmodel)
150 self.assertIn("name: VRouterPort", vrouterport)
151
152 def test_write_multiple_files_from_xtarget(self):
153 """
154 [XOS-GenX] read multiple models as input, print separate files based on +++
155 """
Scott Baker1f7791d2018-10-04 13:21:20 -0700156 args = XOSProcessorArgs(files = [TEST_XPROTO, VROUTER_XPROTO],
157 target = SPLIT_TARGET,
158 output = OUTPUT_DIR,
159 write_to_file = 'target')
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800160 XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700161
162 generated_files = [f for f in os.listdir(OUTPUT_DIR) if not f.startswith('.')]
163 self.assertEqual(len(generated_files), 2)
164
165 xosmodel = open(os.path.join(OUTPUT_DIR, 'xosmodel.txt'), "r").read()
166 vrouterport = open(os.path.join(OUTPUT_DIR, 'vrouterport.txt'), "r").read()
167
168 self.assertIn("name: XOSModel", xosmodel)
169 self.assertIn("name: VRouterPort", vrouterport)
170
Sapan Bhatia4c835602017-07-14 01:13:17 -0400171 def test_skip_django(self):
Scott Baker1f7791d2018-10-04 13:21:20 -0700172 args = XOSProcessorArgs(files = [SKIP_DJANGO_XPROTO],
173 target = 'django.xtarget',
174 output = OUTPUT_DIR,
175 dest_extension = 'py',
176 write_to_file = 'model')
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800177 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700178
179 # should not print a file if options.skip_django = True
180 file = OUTPUT_DIR + '/user.py'
181 self.assertFalse(os.path.isfile(file))
182
183 def test_service_order(self):
Scott Baker1f7791d2018-10-04 13:21:20 -0700184 args = XOSProcessorArgs(files = [BASE_XPROTO, TEST_XPROTO, VROUTER_XPROTO],
185 target = 'service.xtarget',
186 output = OUTPUT_DIR,
187 write_to_file = 'target')
Sapan Bhatiabfb233a2018-02-09 14:53:09 -0800188 output = XOSProcessor.process(args)
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700189
190 model = OUTPUT_DIR + '/models.py'
191 self.assertTrue(os.path.isfile(model))
192 line_num = 0
193
194 for line in open(model).readlines():
195 line_num += 1
196 if line.find('class XOSBase(models.Model, PlModelMixIn):') >= 0:
197 base_line = line_num
198 if line.find('XOSModel(XOSBase):') >= 0:
199 xosmodel_line = line_num
200 if line.find('class VRouterPort(XOSBase):') >= 0:
201 vrouter_line = line_num
202 self.assertLess(base_line, xosmodel_line)
203 self.assertLess(xosmodel_line, vrouter_line)
204
Scott Baker34dc67e2018-10-02 15:57:50 -0700205 def test_field_numbers(self):
Scott Baker1f7791d2018-10-04 13:21:20 -0700206 args = XOSProcessorArgs(files = [FIELDTEST_XPROTO],
207 target = FIELDTEST_TARGET)
Scott Baker34dc67e2018-10-02 15:57:50 -0700208 output = XOSProcessor.process(args)
209
210 def _assert_field(modelname, fieldname, id):
211 self.assertIn("%s,%s,%s" % (modelname, fieldname, id), output)
212
213 _assert_field("Site", "id", 1)
214 _assert_field("Site", "base_field", 2)
215 _assert_field("Site", "base_field2", 3)
216 _assert_field("Site", "otherstuff_field", 102)
217 _assert_field("Site", "slice_field", 201)
218 _assert_field("Site", "slices_ids", 1002)
219
220 _assert_field("Slice", "id", 1)
221 _assert_field("Slice", "base_field", 2)
222 _assert_field("Slice", "base_field2", 3)
223 _assert_field("Slice", "slice_field", 101)
224 _assert_field("Slice", "site", 102)
225
Scott Bakerd87c02a2018-10-29 16:24:29 -0700226 def test_field_numbers(self):
227 args = XOSProcessorArgs(files = [REVERSEFIELDTEST_XPROTO],
228 target = FIELDTEST_TARGET)
229 output = XOSProcessor.process(args)
230
231 def _assert_field(modelname, fieldname, id):
232 self.assertIn("%s,%s,%s" % (modelname, fieldname, id), output)
233
234 # rel_int1s_ids is the reverse link from RelatedToIntermediate1. It gets the related id with no offset, so it
235 # will be assigned 1001. rel_leaf1as_ids inherits from Intermediate1, so its reverse links will all be offset
236 # by 100
237 _assert_field("Leaf1a", "rel_int1s_ids", 1001)
238 _assert_field("Leaf1a", "rel_leaf1as_ids", 1101)
239
240 # rel_int2s_ids is the reverse link from RelatedToIntermediate1. It gets the related id with no offset, so it
241 # will be assigned 1001. rel_leaf1bs_ids inherits from Intermediate1, so its reverse links will all be offset
242 # by 100
243 _assert_field("Leaf1b", "rel_int1s_ids", 1001)
244 _assert_field("Leaf1b", "rel_leaf1bs_ids", 1101)
245
246 # There are no reverse numbers specified for Intermediate2 or Leaf2, so xproto will fall back to automatic
247 # numbering starting at 1900.
248 _assert_field("Leaf2", "rel_int2s_ids", 1900)
249 _assert_field("Leaf2", "rel_leaf2s_ids", 1901)
250
Scott Baker1f7791d2018-10-04 13:21:20 -0700251 def test_unfiltered(self):
252 """ With no include_* args, should get all models """
253 args = XOSProcessorArgs(files = [FILTERTEST_XPROTO],
254 target = FILTERTEST_TARGET)
255 output = XOSProcessor.process(args)
256
257 self.assertEqual(output, "Model1,Model2,Model3,")
258
259 def test_filter_models(self):
260 """ Should only get models specified by include_models """
261 args = XOSProcessorArgs(files = [FILTERTEST_XPROTO],
262 target = FILTERTEST_TARGET,
263 include_models = ["Model1", "Model3"])
264 output = XOSProcessor.process(args)
265
266 self.assertEqual(output, "Model1,Model3,")
267
268 def test_filter_apps(self):
269 """ Should only get models whose apps are specified by include_apps """
270 args = XOSProcessorArgs(files = [FILTERTEST_XPROTO],
271 target = FILTERTEST_TARGET,
272 include_apps = ["core"])
273 output = XOSProcessor.process(args)
274
275 self.assertEqual(output, "Model1,Model2,")
276
277
278
Matteo Scandolo67654fa2017-06-09 09:33:17 -0700279
280if __name__ == '__main__':
Sapan Bhatia4c835602017-07-14 01:13:17 -0400281 unittest.main()