def test_allowed_values_numeric_int(self): ''' Test AllowedValues constraint for numeric integer values. Test if the AllowedValues constraint works for numeric values in any combination of numeric strings or numbers in the constraint and numeric strings or numbers as value. ''' # Allowed values defined as integer numbers schema = constraints.Schema( 'Integer', constraints=[constraints.AllowedValues([1, 2, 4])]) # ... and value as number or string self.assertIsNone(schema.validate_constraints(1)) err = self.assertRaises(exception.StackValidationFailed, schema.validate_constraints, 3) self.assertEqual('"3" is not an allowed value [1, 2, 4]', six.text_type(err)) self.assertIsNone(schema.validate_constraints('1')) err = self.assertRaises(exception.StackValidationFailed, schema.validate_constraints, '3') self.assertEqual('"3" is not an allowed value [1, 2, 4]', six.text_type(err)) # Allowed values defined as integer strings schema = constraints.Schema( 'Integer', constraints=[constraints.AllowedValues(['1', '2', '4'])]) # ... and value as number or string self.assertIsNone(schema.validate_constraints(1)) err = self.assertRaises(exception.StackValidationFailed, schema.validate_constraints, 3) self.assertEqual('"3" is not an allowed value [1, 2, 4]', six.text_type(err)) self.assertIsNone(schema.validate_constraints('1')) err = self.assertRaises(exception.StackValidationFailed, schema.validate_constraints, '3') self.assertEqual('"3" is not an allowed value [1, 2, 4]', six.text_type(err))
def test_allowed_values_numeric_float(self): """Test AllowedValues constraint for numeric floating point values. Test if the AllowedValues constraint works for numeric values in any combination of numeric strings or numbers in the constraint and numeric strings or numbers as value. """ # Allowed values defined as numbers schema = constraints.Schema( 'Number', constraints=[constraints.AllowedValues([1.1, 2.2, 4.4])]) # ... and value as number or string self.assertIsNone(schema.validate_constraints(1.1)) err = self.assertRaises(exception.StackValidationFailed, schema.validate_constraints, 3.3) self.assertEqual('3.3 is not an allowed value [1.1, 2.2, 4.4]', six.text_type(err)) self.assertIsNone(schema.validate_constraints('1.1')) err = self.assertRaises(exception.StackValidationFailed, schema.validate_constraints, '3.3') self.assertEqual('"3.3" is not an allowed value [1.1, 2.2, 4.4]', six.text_type(err)) # Allowed values defined as strings schema = constraints.Schema( 'Number', constraints=[constraints.AllowedValues(['1.1', '2.2', '4.4'])]) # ... and value as number or string self.assertIsNone(schema.validate_constraints(1.1)) err = self.assertRaises(exception.StackValidationFailed, schema.validate_constraints, 3.3) self.assertEqual('3.3 is not an allowed value ["1.1", "2.2", "4.4"]', six.text_type(err)) self.assertIsNone(schema.validate_constraints('1.1')) err = self.assertRaises(exception.StackValidationFailed, schema.validate_constraints, '3.3') self.assertEqual('"3.3" is not an allowed value ["1.1", "2.2", "4.4"]', six.text_type(err))
def test_schema_nested_schema(self): d = { 'type': 'list', 'description': 'A list', 'schema': { '*': { 'type': 'map', 'description': 'A map', 'schema': { 'Foo': { 'type': 'string', 'description': 'A string', 'default': 'wibble', 'required': False, 'constraints': [ { 'length': { 'min': 4, 'max': 8 } }, ] } }, 'required': False, } }, 'required': False, } s = constraints.Schema(constraints.Schema.STRING, 'A string', default='wibble', constraints=[constraints.Length(4, 8)]) m = constraints.Schema(constraints.Schema.MAP, 'A map', schema={'Foo': s}) l = constraints.Schema(constraints.Schema.LIST, 'A list', schema=m) self.assertEqual(d, dict(l))
def test_schema_all(self): d = { 'type': 'string', 'description': 'A string', 'default': 'wibble', 'required': False, 'constraints': [ {'length': {'min': 4, 'max': 8}}, ] } s = constraints.Schema(constraints.Schema.STRING, 'A string', default='wibble', constraints=[constraints.Length(4, 8)]) self.assertEqual(d, dict(s))
def test_to_schema_type_num(self): """Test Schema.to_schema_type method for type Number.""" schema = constraints.Schema('Number') res = schema.to_schema_type(1) self.assertIsInstance(res, int) res = schema.to_schema_type('1') self.assertIsInstance(res, int) res = schema.to_schema_type(1.5) self.assertIsInstance(res, float) res = schema.to_schema_type('1.5') self.assertIsInstance(res, float) self.assertEqual(1.5, res) err = self.assertRaises(ValueError, schema.to_schema_type, 'foo') self.assertEqual('Value "foo" is invalid for data type "Number".', six.text_type(err))
def test_to_schema_type_boolean(self): """Test Schema.to_schema_type method for type Boolean.""" schema = constraints.Schema('Boolean') true_values = [1, '1', True, 'true', 'True', 'yes', 'Yes'] for v in true_values: res = schema.to_schema_type(v) self.assertIsInstance(res, bool) self.assertTrue(res) false_values = [0, '0', False, 'false', 'False', 'No', 'no'] for v in false_values: res = schema.to_schema_type(v) self.assertIsInstance(res, bool) self.assertFalse(res) err = self.assertRaises(ValueError, schema.to_schema_type, 'foo') self.assertEqual('Value "foo" is invalid for data type "Boolean".', six.text_type(err))
def test_to_schema_type_int(self): """Test Schema.to_schema_type method for type Integer.""" schema = constraints.Schema('Integer') # test valid values, i.e. integeres as string or number res = schema.to_schema_type(1) self.assertIsInstance(res, int) res = schema.to_schema_type('1') self.assertIsInstance(res, int) # test invalid numeric values, i.e. floating point numbers err = self.assertRaises(ValueError, schema.to_schema_type, 1.5) self.assertEqual('Value "1.5" is invalid for data type "Integer".', six.text_type(err)) err = self.assertRaises(ValueError, schema.to_schema_type, '1.5') self.assertEqual('Value "1.5" is invalid for data type "Integer".', six.text_type(err)) # test invalid string values err = self.assertRaises(ValueError, schema.to_schema_type, 'foo') self.assertEqual('Value "foo" is invalid for data type "Integer".', six.text_type(err))
def test_range_invalid_type(self): schema = constraints.Schema('String', constraints=[constraints.Range(1, 10)]) err = self.assertRaises(exception.InvalidSchemaError, schema.validate) self.assertIn('Range constraint invalid for String', six.text_type(err))
def test_without_warn_only_required(self, mock_warn): constraints.Schema(constraints.Schema.STRING, 'A string', required=True) self.assertEqual(0, mock_warn.call_count)
def test_schema_validate_good(self): s = constraints.Schema(constraints.Schema.STRING, 'A string', default='wibble', constraints=[constraints.Length(4, 8)]) self.assertIsNone(s.validate())
def test_schema_validate_fail(self): s = constraints.Schema(constraints.Schema.STRING, 'A string', default='wibble', required=True, constraints=[constraints.Range(max=4)]) err = self.assertRaises(constraints.InvalidSchemaError, s.validate) self.assertIn('Range constraint invalid for String', str(err))
def test_modulo_invalid_type(self): schema = constraints.Schema('String', constraints=[constraints.Modulo(2, 1)]) err = self.assertRaises(exception.InvalidSchemaError, schema.validate) self.assertIn('Modulo constraint invalid for String', six.text_type(err))
def test_allowed_pattern_invalid_type(self): schema = constraints.Schema( 'Integer', constraints=[constraints.AllowedPattern('[0-9]*')]) err = self.assertRaises(exception.InvalidSchemaError, schema.validate) self.assertIn('AllowedPattern constraint invalid for Integer', six.text_type(err))
def test_without_warn_only_default(self, mock_warn): constraints.Schema(constraints.Schema.STRING, 'A string', default='wibble') self.assertEqual(0, mock_warn.call_count)
def test_to_schema_type_map(self): """Test Schema.to_schema_type method for type Map.""" schema = constraints.Schema('Map') res = schema.to_schema_type({'a': 'aa', 'b': 'bb'}) self.assertIsInstance(res, dict) self.assertEqual({'a': 'aa', 'b': 'bb'}, res)
def test_schema_invalid_type(self): self.assertRaises(exception.InvalidSchemaError, constraints.Schema, 'String', schema=constraints.Schema('String'))
def test_without_warn_only_default(self): constraints.Schema(constraints.Schema.STRING, 'A string', default='wibble') self.assertEqual(0, len(self.warnings.captures))
def test_without_warn_only_required(self): constraints.Schema(constraints.Schema.STRING, 'A string', required=True) self.assertEqual(0, len(self.warnings.captures))
def test_to_schema_type_list(self): """Test Schema.to_schema_type method for type List.""" schema = constraints.Schema('List') res = schema.to_schema_type(['a', 'b']) self.assertIsInstance(res, list) self.assertEqual(['a', 'b'], res)
def test_length_invalid_type(self): schema = constraints.Schema('Integer', constraints=[constraints.Length(1, 10)]) err = self.assertRaises(exception.InvalidSchemaError, schema.validate) self.assertIn('Length constraint invalid for Integer', six.text_type(err))