blob: 051b1d0afef5c3ee12da6491b81a692039ff3744 [file] [log] [blame]
Matteo Scandolo920e8fd2017-08-08 13:05:24 -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
Zack Williams6bb2cfe2019-03-27 15:01:45 -070015from __future__ import absolute_import
16from . import helpers # noqa: F401
Matteo Scandolo9ce18252017-06-22 10:48:25 -070017import unittest
Matteo Scandolo9ce18252017-06-22 10:48:25 -070018from tosca.parser import TOSCA_Parser
19
Matteo Scandolo9ce18252017-06-22 10:48:25 -070020
Zack Williams6bb2cfe2019-03-27 15:01:45 -070021class TOSCA_Parser_Test(unittest.TestCase):
Matteo Scandolo485b7132017-06-30 11:46:47 -070022 def test_get_tosca_models_by_name(self):
Matteo Scandolo9ce18252017-06-22 10:48:25 -070023 """
Matteo Scandolo485b7132017-06-30 11:46:47 -070024 [TOSCA_Parser] get_tosca_models_by_name: should extract models from the TOSCA recipe and store them in a dict
Matteo Scandolo9ce18252017-06-22 10:48:25 -070025 """
Zack Williams6bb2cfe2019-03-27 15:01:45 -070026
Matteo Scandolo485b7132017-06-30 11:46:47 -070027 class FakeNode:
28 def __init__(self, name):
29 self.name = name
Matteo Scandolo9ce18252017-06-22 10:48:25 -070030
Matteo Scandolo485b7132017-06-30 11:46:47 -070031 class FakeTemplate:
Zack Williams6bb2cfe2019-03-27 15:01:45 -070032 nodetemplates = [FakeNode("model1"), FakeNode("model2")]
Matteo Scandolo9ce18252017-06-22 10:48:25 -070033
Matteo Scandolo485b7132017-06-30 11:46:47 -070034 res = TOSCA_Parser.get_tosca_models_by_name(FakeTemplate)
Zack Williams6bb2cfe2019-03-27 15:01:45 -070035 self.assertIsInstance(res["model1"], FakeNode)
36 self.assertIsInstance(res["model2"], FakeNode)
Matteo Scandolo8bbb03a2017-07-05 14:03:33 -070037
Zack Williams6bb2cfe2019-03-27 15:01:45 -070038 self.assertEqual(res["model1"].name, "model1")
39 self.assertEqual(res["model2"].name, "model2")
Matteo Scandolodf2600b2017-07-05 17:01:29 -070040
Matteo Scandolo8bbb03a2017-07-05 14:03:33 -070041 def test_populate_dependencies(self):
42 """
Zack Williams6bb2cfe2019-03-27 15:01:45 -070043 [TOSCA_Parser] populate_dependencies: if a recipe has dependencies, it
44 should find the ID of the requirements and add it to the model
Matteo Scandolo8bbb03a2017-07-05 14:03:33 -070045 """
Zack Williams6bb2cfe2019-03-27 15:01:45 -070046
Matteo Scandolo8bbb03a2017-07-05 14:03:33 -070047 class FakeRecipe:
48 requirements = [
49 {
Zack Williams6bb2cfe2019-03-27 15:01:45 -070050 "site": {
51 "node": "site_onlab",
52 "relationship": "tosca.relationship.BelongsToOne",
Matteo Scandolo8bbb03a2017-07-05 14:03:33 -070053 }
54 }
55 ]
56
57 class FakeSite:
58 id = 1
Zack Williams6bb2cfe2019-03-27 15:01:45 -070059 name = "onlab"
Matteo Scandolo8bbb03a2017-07-05 14:03:33 -070060
61 class FakeModel:
Zack Williams6bb2cfe2019-03-27 15:01:45 -070062 name = "test@opencord.org"
Matteo Scandolo8bbb03a2017-07-05 14:03:33 -070063
Zack Williams6bb2cfe2019-03-27 15:01:45 -070064 saved_models = {"site_onlab": FakeSite}
Matteo Scandolo8bbb03a2017-07-05 14:03:33 -070065
Zack Williams6bb2cfe2019-03-27 15:01:45 -070066 model = TOSCA_Parser.populate_dependencies(
67 FakeModel, FakeRecipe.requirements, saved_models
68 )
Matteo Scandolodf2600b2017-07-05 17:01:29 -070069 self.assertEqual(model.site_id, 1)
70
71 def test_get_ordered_models_template(self):
72 """
73 [TOSCA_Parser] get_ordered_models_template: Create a list of templates based on topsorted models
74 """
Zack Williams6bb2cfe2019-03-27 15:01:45 -070075 ordered_models = ["foo", "bar"]
Matteo Scandolodf2600b2017-07-05 17:01:29 -070076
Zack Williams6bb2cfe2019-03-27 15:01:45 -070077 templates = {"foo": "foo_template", "bar": "bar_template"}
Matteo Scandolodf2600b2017-07-05 17:01:29 -070078
Zack Williams6bb2cfe2019-03-27 15:01:45 -070079 ordered_templates = TOSCA_Parser.get_ordered_models_template(
80 ordered_models, templates
81 )
Matteo Scandolodf2600b2017-07-05 17:01:29 -070082
Zack Williams6bb2cfe2019-03-27 15:01:45 -070083 self.assertEqual(ordered_templates[0], "foo_template")
84 self.assertEqual(ordered_templates[1], "bar_template")
Matteo Scandolodf2600b2017-07-05 17:01:29 -070085
86 def test_topsort_dependencies(self):
87 """
88 [TOSCA_Parser] topsort_dependencies: Create a list of models based on dependencies
89 """
Zack Williams6bb2cfe2019-03-27 15:01:45 -070090
Matteo Scandolodf2600b2017-07-05 17:01:29 -070091 class FakeTemplate:
92 def __init__(self, name, deps):
93 self.name = name
Zack Williams6bb2cfe2019-03-27 15:01:45 -070094 self.dependencies_names = deps
Matteo Scandolodf2600b2017-07-05 17:01:29 -070095
96 templates = {
Zack Williams6bb2cfe2019-03-27 15:01:45 -070097 "deps": FakeTemplate("deps", ["main"]),
98 "main": FakeTemplate("main", []),
Matteo Scandolodf2600b2017-07-05 17:01:29 -070099 }
100
101 sorted = TOSCA_Parser.topsort_dependencies(templates)
102
Zack Williams6bb2cfe2019-03-27 15:01:45 -0700103 self.assertEqual(sorted[0], "main")
104 self.assertEqual(sorted[1], "deps")
Matteo Scandolodf2600b2017-07-05 17:01:29 -0700105
106 def test_compute_dependencies(self):
107 """
Zack Williams6bb2cfe2019-03-27 15:01:45 -0700108 [TOSCA_Parser] compute_dependencies: augment the TOSCA nodetemplate
109 with information on requirements (aka related models)
Matteo Scandolodf2600b2017-07-05 17:01:29 -0700110 """
111
Zack Williams6bb2cfe2019-03-27 15:01:45 -0700112 parser = TOSCA_Parser("", "user", "pass")
Matteo Scandolodf2600b2017-07-05 17:01:29 -0700113
114 class FakeNode:
115 def __init__(self, name, requirements):
116 self.name = name
117 self.requirements = requirements
118
Zack Williams6bb2cfe2019-03-27 15:01:45 -0700119 main = FakeNode("main", [])
120 dep = FakeNode("dep", [{"relation": {"node": "main"}}])
Matteo Scandolodf2600b2017-07-05 17:01:29 -0700121
Zack Williams6bb2cfe2019-03-27 15:01:45 -0700122 models_by_name = {"main": main, "dep": dep}
Matteo Scandolodf2600b2017-07-05 17:01:29 -0700123
124 class FakeTemplate:
125 nodetemplates = [dep, main]
126
127 parser.compute_dependencies(FakeTemplate, models_by_name)
128
129 templates = FakeTemplate.nodetemplates
130 augmented_dep = templates[0]
131 augmented_main = templates[1]
132
133 self.assertIsInstance(augmented_dep.dependencies[0], FakeNode)
Zack Williams6bb2cfe2019-03-27 15:01:45 -0700134 self.assertEqual(augmented_dep.dependencies[0].name, "main")
135 self.assertEqual(augmented_dep.dependencies_names[0], "main")
Matteo Scandolodf2600b2017-07-05 17:01:29 -0700136
137 self.assertEqual(len(augmented_main.dependencies), 0)
138 self.assertEqual(len(augmented_main.dependencies_names), 0)
139
140 def test_populate_model(self):
141 """
142 [TOSCA_Parser] populate_model: augment the GRPC model with data from TOSCA
143 """
Zack Williams6bb2cfe2019-03-27 15:01:45 -0700144
Matteo Scandolodf2600b2017-07-05 17:01:29 -0700145 class FakeModel:
146 pass
147
Zack Williams6bb2cfe2019-03-27 15:01:45 -0700148 data = {"name": "test", "foo": "bar", "number": 1}
Matteo Scandolodf2600b2017-07-05 17:01:29 -0700149
150 model = TOSCA_Parser.populate_model(FakeModel, data)
151
Zack Williams6bb2cfe2019-03-27 15:01:45 -0700152 self.assertEqual(model.name, "test")
153 self.assertEqual(model.foo, "bar")
Matteo Scandolodf2600b2017-07-05 17:01:29 -0700154 self.assertEqual(model.number, 1)
155
Matteo Scandolo5ccdb132018-01-17 14:02:12 -0800156 def test_populate_model_error(self):
157 """
158 [TOSCA_Parser] populate_model: should print a meaningful error message
159 """
160
161 class FakeModel:
162
163 model_name = "FakeModel"
164
165 def __setattr__(self, name, value):
Zack Williams6bb2cfe2019-03-27 15:01:45 -0700166 if name == "foo":
167 raise TypeError("reported exception")
Matteo Scandolo5ccdb132018-01-17 14:02:12 -0800168 else:
169 super(FakeModel, self).__setattr__(name, value)
170
Zack Williams6bb2cfe2019-03-27 15:01:45 -0700171 data = {"name": "test", "foo": None, "number": 1}
Matteo Scandolo5ccdb132018-01-17 14:02:12 -0800172
173 model = FakeModel()
174
175 with self.assertRaises(Exception) as e:
176 model = TOSCA_Parser.populate_model(model, data)
Zack Williams6bb2cfe2019-03-27 15:01:45 -0700177 self.assertEqual(
178 str(e.exception),
179 'Failed to set None on field foo for class FakeModel, Exception was: "reported exception"',
180 )
Matteo Scandolo5ccdb132018-01-17 14:02:12 -0800181
Matteo Scandolodf2600b2017-07-05 17:01:29 -0700182 def test_translate_exception(self):
183 """
184 [TOSCA_Parser] translate_exception: convert a TOSCA Parser exception in a user readable string
185 """
186 e = TOSCA_Parser._translate_exception("Non tosca exception")
187 self.assertEqual(e, "Non tosca exception")
188
Zack Williams6bb2cfe2019-03-27 15:01:45 -0700189 e = TOSCA_Parser._translate_exception(
190 """
Matteo Scandolodf2600b2017-07-05 17:01:29 -0700191MissingRequiredFieldError: some message
192 followed by unreadable
193 and mystic
194 python error
195 starting at line
196 38209834 of some file
Matteo Scandolo1fedfae2017-10-09 13:57:00 -0700197UnknownFieldError: with some message
198 followed by useless things
199ImportError: with some message
200 followed by useless things
201InvalidTypeError: with some message
202 followed by useless things
203TypeMismatchError: with some message
204 followed by useless things
Zack Williams6bb2cfe2019-03-27 15:01:45 -0700205 """
206 )
207 self.assertEqual(
208 e,
209 """MissingRequiredFieldError: some message
Matteo Scandolo1fedfae2017-10-09 13:57:00 -0700210UnknownFieldError: with some message
211ImportError: with some message
212InvalidTypeError: with some message
213TypeMismatchError: with some message
Zack Williams6bb2cfe2019-03-27 15:01:45 -0700214""",
215 )