summaryrefslogtreecommitdiffstats
path: root/tosca2heat/tosca-parser/toscaparser/tests/test_datatypes.py
diff options
context:
space:
mode:
authorshangxdy <shang.xiaodong@zte.com.cn>2016-04-07 14:08:49 -0400
committershangxdy <shang.xiaodong@zte.com.cn>2016-04-07 14:59:30 -0400
commitc8201c119ec686e79797721156767685fe848aca (patch)
treecce6aa15ded38d89c18a14b76c21f21e0b1a24f7 /tosca2heat/tosca-parser/toscaparser/tests/test_datatypes.py
parent4e4c86a06d58b1816c074c7f9da4c58bbf10368c (diff)
Update tosca lib to version 0.5
Use tosca-parser and heat-translator to analyze to the basic nfv-tosca type definitions, and use simple tosca new feature such as policy, group and trigger, which are now supported by the latest version of tosca-parser and heat-translator. JIRA:PARSER-18 Change-Id: I797bcacbb5b32005d0aeb0f3f32851ac96e30f01 Signed--off-by: shangxdy <shang.xiaodong@zte.com.cn> Signed-off-by: shangxdy <shang.xiaodong@zte.com.cn>
Diffstat (limited to 'tosca2heat/tosca-parser/toscaparser/tests/test_datatypes.py')
-rw-r--r--tosca2heat/tosca-parser/toscaparser/tests/test_datatypes.py408
1 files changed, 408 insertions, 0 deletions
diff --git a/tosca2heat/tosca-parser/toscaparser/tests/test_datatypes.py b/tosca2heat/tosca-parser/toscaparser/tests/test_datatypes.py
new file mode 100644
index 0000000..0e613b2
--- /dev/null
+++ b/tosca2heat/tosca-parser/toscaparser/tests/test_datatypes.py
@@ -0,0 +1,408 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import os
+
+from testtools.testcase import skip
+from toscaparser.common import exception
+from toscaparser.dataentity import DataEntity
+from toscaparser.elements.datatype import DataType
+from toscaparser.parameters import Input
+from toscaparser.tests.base import TestCase
+from toscaparser.tosca_template import ToscaTemplate
+from toscaparser.utils.gettextutils import _
+from toscaparser.utils import yamlparser
+
+
+class DataTypeTest(TestCase):
+
+ custom_type_schema = '''
+ tosca.my.datatypes.PeopleBase:
+ properties:
+ name:
+ type: string
+ required: true
+ constraints:
+ - min_length: 2
+ gender:
+ type: string
+ default: unknown
+
+ tosca.my.datatypes.People:
+ derived_from: tosca.my.datatypes.PeopleBase
+ properties:
+ addresses:
+ type: map
+ required: false
+ entry_schema:
+ type: string
+ contacts:
+ type: list
+ required: false
+ entry_schema:
+ type: tosca.my.datatypes.ContactInfo
+
+ tosca.my.datatypes.ContactInfo:
+ description: simple contact information
+ properties:
+ contact_name:
+ type: string
+ required: true
+ constraints:
+ - min_length: 2
+ contact_email:
+ type: string
+ contact_phone:
+ type: string
+
+ tosca.my.datatypes.TestLab:
+ properties:
+ temperature:
+ type: range
+ required: false
+ constraints:
+ - in_range: [-256, UNBOUNDED]
+ humidity:
+ type: range
+ required: false
+ constraints:
+ - in_range: [-256, INFINITY]
+ '''
+ custom_type_def = yamlparser.simple_parse(custom_type_schema)
+
+ def test_empty_template(self):
+ value_snippet = ''
+ value = yamlparser.simple_parse(value_snippet)
+ self.assertEqual(value, {})
+
+ # TODO(Matt) - opened as bug 1555300
+ # Need a test for PortSpec normative data type
+ # that tests the spec. requirement: "A valid PortSpec
+ # must have at least one of the following properties:
+ # target, target_range, source or source_range."
+ # TODO(Matt) - opened as bug 1555310
+ # test PortSpec value for source and target
+ # against the source_range and target_range
+ # when specified.
+ def test_built_in_datatype(self):
+ value_snippet = '''
+ private_network:
+ network_name: private
+ network_id: 3e54214f-5c09-1bc9-9999-44100326da1b
+ addresses: [ 10.111.128.10 ]
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('tosca.datatypes.network.NetworkInfo',
+ value.get('private_network'))
+ self.assertIsNotNone(data.validate())
+
+ value_snippet = '''
+ portspec_valid:
+ protocol: tcp
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('tosca.datatypes.network.PortSpec',
+ value.get('portspec_valid'))
+ self.assertIsNotNone(data.validate())
+
+ value_snippet = '''
+ portspec_invalid:
+ protocol: xyz
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('tosca.datatypes.network.PortSpec',
+ value.get('portspec_invalid'))
+ err = self.assertRaises(exception.ValidationError, data.validate)
+ self.assertEqual(_('The value "xyz" of property "protocol" is not '
+ 'valid. Expected a value from "[udp, tcp, igmp]".'
+ ),
+ err.__str__())
+
+ def test_built_in_datatype_with_short_name(self):
+ value_snippet = '''
+ ethernet_port:
+ port_name: port1
+ port_id: 2c0c7a37-691a-23a6-7709-2d10ad041467
+ network_id: 3e54214f-5c09-1bc9-9999-44100326da1b
+ mac_address: f1:18:3b:41:92:1e
+ addresses: [ 172.24.9.102 ]
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('PortInfo', value.get('ethernet_port'))
+ self.assertIsNotNone(data.validate())
+
+ def test_built_in_datatype_without_properties(self):
+ value_snippet = '''
+ 2
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ datatype = DataType('PortDef')
+ self.assertEqual('integer', datatype.value_type)
+ data = DataEntity('PortDef', value)
+ self.assertIsNotNone(data.validate())
+
+ @skip('The example in TOSCA spec may have some problem.')
+ def test_built_in_nested_datatype(self):
+ value_snippet = '''
+ user_port:
+ protocol: tcp
+ target: [50000]
+ source: [9000]
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('PortSpec', value.get('user_port'))
+ self.assertIsNotNone(data.validate())
+
+ def test_built_in_nested_datatype_portdef(self):
+ tpl_snippet = '''
+ inputs:
+ db_port:
+ type: PortDef
+ description: Port for the MySQL database
+ '''
+ inputs = yamlparser.simple_parse(tpl_snippet)['inputs']
+ name, attrs = list(inputs.items())[0]
+ input = Input(name, attrs)
+ self.assertIsNone(input.validate(3360))
+ err = self.assertRaises(exception.ValidationError, input.validate,
+ 336000)
+ self.assertEqual(_('The value "336000" of property "None" is out of '
+ 'range "(min:1, max:65535)".'),
+ err.__str__())
+
+ def test_custom_datatype(self):
+ value_snippet = '''
+ name: Mike
+ gender: male
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('tosca.my.datatypes.PeopleBase', value,
+ DataTypeTest.custom_type_def)
+ self.assertIsNotNone(data.validate())
+
+ def test_custom_datatype_with_parent(self):
+ value_snippet = '''
+ name: Mike
+ gender: male
+ contacts:
+ - {contact_name: Tom,
+ contact_email: tom@email.com,
+ contact_phone: '123456789'}
+ - {contact_name: Jerry,
+ contact_email: jerry@email.com,
+ contact_phone: '321654987'}
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('tosca.my.datatypes.People', value,
+ DataTypeTest.custom_type_def)
+ self.assertIsNotNone(data.validate())
+
+ # [Tom, Jerry] is not a dict, it can't be a value of datatype PeopleBase
+ def test_non_dict_value_for_datatype(self):
+ value_snippet = '''
+ [Tom, Jerry]
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('tosca.my.datatypes.PeopleBase', value,
+ DataTypeTest.custom_type_def)
+ error = self.assertRaises(exception.TypeMismatchError, data.validate)
+ self.assertEqual(_('[\'Tom\', \'Jerry\'] must be of type '
+ '"tosca.my.datatypes.PeopleBase".'),
+ error.__str__())
+
+ # 'nema' is an invalid field name
+ def test_field_error_in_dataentity(self):
+ value_snippet = '''
+ nema: Mike
+ gender: male
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('tosca.my.datatypes.PeopleBase', value,
+ DataTypeTest.custom_type_def)
+ error = self.assertRaises(exception.UnknownFieldError, data.validate)
+ self.assertEqual(_('Data value of type '
+ '"tosca.my.datatypes.PeopleBase" contains unknown '
+ 'field "nema". Refer to the definition to verify '
+ 'valid values.'),
+ error.__str__())
+
+ def test_default_field_in_dataentity(self):
+ value_snippet = '''
+ name: Mike
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('tosca.my.datatypes.PeopleBase', value,
+ DataTypeTest.custom_type_def)
+ data = data.validate()
+ self.assertEqual('unknown', data.get('gender'))
+
+ # required field 'name' is missing
+ def test_missing_field_in_dataentity(self):
+ value_snippet = '''
+ gender: male
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('tosca.my.datatypes.PeopleBase', value,
+ DataTypeTest.custom_type_def)
+ error = self.assertRaises(exception.MissingRequiredFieldError,
+ data.validate)
+ self.assertEqual(_('Data value of type '
+ '"tosca.my.datatypes.PeopleBase" is missing '
+ 'required field "[\'name\']".'),
+ error.__str__())
+
+ # the value of name field is not a string
+ def test_type_error_in_dataentity(self):
+ value_snippet = '''
+ name: 123
+ gender: male
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('tosca.my.datatypes.PeopleBase', value,
+ DataTypeTest.custom_type_def)
+ error = self.assertRaises(ValueError, data.validate)
+ self.assertEqual(_('"123" is not a string.'), error.__str__())
+
+ # the value of name doesn't meet the defined constraint
+ def test_value_error_in_dataentity(self):
+ value_snippet = '''
+ name: M
+ gender: male
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('tosca.my.datatypes.PeopleBase', value,
+ DataTypeTest.custom_type_def)
+ error = self.assertRaises(exception.ValidationError, data.validate)
+ self.assertEqual(_('Length of value "M" of property "name" must be '
+ 'at least "2".'), error.__str__())
+
+ # value of addresses doesn't fit the entry_schema
+ def test_validation_in_collection_entry(self):
+ value_snippet = '''
+ name: Mike
+ gender: male
+ addresses: {Home: 1, Office: 9 bar avenue}
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('tosca.my.datatypes.People', value,
+ DataTypeTest.custom_type_def)
+ error = self.assertRaises(ValueError, data.validate)
+ self.assertEqual(_('"1" is not a string.'), error.__str__())
+
+ # 'contact_pone' is an invalid attribute name in nested datatype below
+ def test_validation_in_nested_datatype(self):
+ value_snippet = '''
+ name: Mike
+ gender: male
+ contacts:
+ - {contact_name: Tom,
+ contact_email: tom@email.com,
+ contact_pone: '123456789'}
+ - {contact_name: Jerry,
+ contact_email: jerry@email.com,
+ contact_phone: '321654987'}
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('tosca.my.datatypes.People', value,
+ DataTypeTest.custom_type_def)
+ error = self.assertRaises(exception.UnknownFieldError, data.validate)
+ self.assertEqual(_('Data value of type '
+ '"tosca.my.datatypes.ContactInfo" contains unknown '
+ 'field "contact_pone". Refer to the definition to '
+ 'verify valid values.'),
+ error.__str__())
+
+ def test_datatype_in_current_template(self):
+ tpl_path = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ "data/datatypes/test_custom_datatypes_in_current_template.yaml")
+ self.assertIsNotNone(ToscaTemplate(tpl_path))
+
+ def test_datatype_in_template_positive(self):
+ tpl_path = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ "data/datatypes/test_custom_datatypes_positive.yaml")
+ self.assertIsNotNone(ToscaTemplate(tpl_path))
+
+ def test_datatype_in_template_invalid_value(self):
+ tpl_path = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ "data/datatypes/test_custom_datatypes_value_error.yaml")
+ self.assertRaises(exception.ValidationError, ToscaTemplate, tpl_path)
+ exception.ExceptionCollector.assertExceptionMessage(
+ ValueError,
+ _('"[\'1 foo street\', \'9 bar avenue\']" is not a map.'))
+
+ def test_datatype_in_template_nested_datatype_error(self):
+ tpl_path = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ "data/datatypes/test_custom_datatypes_nested_datatype_error.yaml")
+ self.assertRaises(exception.ValidationError, ToscaTemplate, tpl_path)
+ exception.ExceptionCollector.assertExceptionMessage(
+ ValueError, _('"123456789" is not a string.'))
+
+ def test_valid_range_type(self):
+ value_snippet = '''
+ user_port:
+ protocol: tcp
+ target_range: [20000, 60000]
+ source_range: [1000, 3000]
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('PortSpec', value.get('user_port'))
+ self.assertIsNotNone(data.validate())
+
+ def test_invalid_range_datatype(self):
+ value_snippet = '''
+ user_port:
+ protocol: tcp
+ target_range: [20000]
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('PortSpec', value.get('user_port'))
+ err = self.assertRaises(ValueError, data.validate)
+ self.assertEqual(_('"[20000]" is not a valid range.'
+ ),
+ err.__str__())
+
+ value_snippet = '''
+ user_port:
+ protocol: tcp
+ target_range: [20000, 3000]
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('PortSpec', value.get('user_port'))
+ err = self.assertRaises(ValueError, data.validate)
+ self.assertEqual(_('"[20000, 3000]" is not a valid range.'
+ ),
+ err.__str__())
+
+ value_snippet = '''
+ humidity: [-100, 100]
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('tosca.my.datatypes.TestLab',
+ value, DataTypeTest.custom_type_def)
+ err = self.assertRaises(exception.InvalidSchemaError,
+ lambda: data.validate())
+ self.assertEqual(_('The property "in_range" expects comparable values.'
+ ),
+ err.__str__())
+
+ def test_range_unbounded(self):
+ value_snippet = '''
+ temperature: [-100, 999999]
+ '''
+ value = yamlparser.simple_parse(value_snippet)
+ data = DataEntity('tosca.my.datatypes.TestLab', value,
+ DataTypeTest.custom_type_def)
+ self.assertIsNotNone(data.validate())