2023-08-15 14:28:04 +00:00
package jsonschema
import (
"testing"
"github.com/stretchr/testify/assert"
2024-04-25 11:23:50 +00:00
"github.com/stretchr/testify/require"
2023-08-15 14:28:04 +00:00
)
2023-09-07 14:36:06 +00:00
func TestSchemaValidateTypeNames ( t * testing . T ) {
2023-08-15 14:28:04 +00:00
var err error
toSchema := func ( s string ) * Schema {
return & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : Type ( s ) ,
} ,
} ,
}
}
err = toSchema ( "string" ) . validate ( )
assert . NoError ( t , err )
err = toSchema ( "boolean" ) . validate ( )
assert . NoError ( t , err )
err = toSchema ( "number" ) . validate ( )
assert . NoError ( t , err )
err = toSchema ( "integer" ) . validate ( )
assert . NoError ( t , err )
err = toSchema ( "int" ) . validate ( )
assert . EqualError ( t , err , "type int is not a recognized json schema type. Please use \"integer\" instead" )
err = toSchema ( "float" ) . validate ( )
assert . EqualError ( t , err , "type float is not a recognized json schema type. Please use \"number\" instead" )
err = toSchema ( "bool" ) . validate ( )
assert . EqualError ( t , err , "type bool is not a recognized json schema type. Please use \"boolean\" instead" )
err = toSchema ( "foobar" ) . validate ( )
assert . EqualError ( t , err , "type foobar is not a recognized json schema type" )
}
2023-09-07 14:36:06 +00:00
func TestSchemaLoadIntegers ( t * testing . T ) {
schema , err := Load ( "./testdata/schema-load-int/schema-valid.json" )
assert . NoError ( t , err )
assert . Equal ( t , int64 ( 1 ) , schema . Properties [ "abc" ] . Default )
2023-09-08 12:07:22 +00:00
assert . Equal ( t , [ ] any { int64 ( 1 ) , int64 ( 2 ) , int64 ( 3 ) } , schema . Properties [ "abc" ] . Enum )
2023-11-30 16:07:45 +00:00
assert . Equal ( t , int64 ( 5 ) , schema . Properties [ "def" ] . Const )
2023-09-07 14:36:06 +00:00
}
func TestSchemaLoadIntegersWithInvalidDefault ( t * testing . T ) {
_ , err := Load ( "./testdata/schema-load-int/schema-invalid-default.json" )
assert . EqualError ( t , err , "failed to parse default value for property abc: expected integer value, got: 1.1" )
}
2023-09-08 12:07:22 +00:00
func TestSchemaLoadIntegersWithInvalidEnums ( t * testing . T ) {
_ , err := Load ( "./testdata/schema-load-int/schema-invalid-enum.json" )
assert . EqualError ( t , err , "failed to parse enum value 2.4 at index 1 for property abc: expected integer value, got: 2.4" )
}
2023-11-30 16:07:45 +00:00
func TestSchemaLoadIntergersWithInvalidConst ( t * testing . T ) {
_ , err := Load ( "./testdata/schema-load-int/schema-invalid-const.json" )
assert . EqualError ( t , err , "failed to parse const value for property def: expected integer value, got: 5.1" )
}
2023-09-07 14:36:06 +00:00
func TestSchemaValidateDefaultType ( t * testing . T ) {
invalidSchema := & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : "number" ,
Default : "abc" ,
} ,
} ,
}
err := invalidSchema . validate ( )
assert . EqualError ( t , err , "type validation for default value of property foo failed: expected type float, but value is \"abc\"" )
validSchema := & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : "boolean" ,
Default : true ,
} ,
} ,
}
err = validSchema . validate ( )
assert . NoError ( t , err )
}
2023-09-08 12:07:22 +00:00
func TestSchemaValidateEnumType ( t * testing . T ) {
invalidSchema := & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : "boolean" ,
Enum : [ ] any { true , "false" } ,
} ,
} ,
}
err := invalidSchema . validate ( )
assert . EqualError ( t , err , "type validation for enum at index 1 failed for property foo: expected type boolean, but value is \"false\"" )
validSchema := & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : "boolean" ,
Enum : [ ] any { true , false } ,
} ,
} ,
}
err = validSchema . validate ( )
assert . NoError ( t , err )
}
func TestSchemaValidateErrorWhenDefaultValueIsNotInEnums ( t * testing . T ) {
invalidSchema := & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : "string" ,
Default : "abc" ,
Enum : [ ] any { "def" , "ghi" } ,
} ,
} ,
}
err := invalidSchema . validate ( )
assert . EqualError ( t , err , "list of enum values for property foo does not contain default value abc: [def ghi]" )
validSchema := & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : "string" ,
Default : "abc" ,
Enum : [ ] any { "def" , "ghi" , "abc" } ,
} ,
} ,
}
err = validSchema . validate ( )
assert . NoError ( t , err )
}
2023-09-25 09:53:38 +00:00
func TestSchemaValidatePatternType ( t * testing . T ) {
s := & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : "number" ,
Pattern : "abc" ,
} ,
} ,
}
assert . EqualError ( t , s . validate ( ) , "property \"foo\" has a non-empty regex pattern \"abc\" specified. Patterns are only supported for string properties" )
s = & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : "string" ,
Pattern : "abc" ,
} ,
} ,
}
assert . NoError ( t , s . validate ( ) )
}
func TestSchemaValidateIncorrectRegex ( t * testing . T ) {
s := & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : "string" ,
// invalid regex, missing the closing brace
Pattern : "(abc" ,
} ,
} ,
}
assert . EqualError ( t , s . validate ( ) , "invalid regex pattern \"(abc\" provided for property \"foo\": error parsing regexp: missing closing ): `(abc`" )
}
2023-11-07 12:35:59 +00:00
func TestSchemaDefaultValueIsNotValidatedAgainstPattern ( t * testing . T ) {
2023-09-25 09:53:38 +00:00
s := & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : "string" ,
Pattern : "abc" ,
Default : "def" ,
} ,
} ,
}
assert . NoError ( t , s . validate ( ) )
}
func TestSchemaValidatePatternEnum ( t * testing . T ) {
s := & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : "string" ,
Pattern : "a.*c" ,
Enum : [ ] any { "abc" , "def" , "abbc" } ,
} ,
} ,
}
assert . EqualError ( t , s . validate ( ) , "enum value \"def\" at index 1 for property \"foo\" does not match specified regex pattern: \"a.*c\"" )
s = & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : "string" ,
Pattern : "a.*d" ,
Enum : [ ] any { "abd" , "axybgd" , "abbd" } ,
} ,
} ,
}
assert . NoError ( t , s . validate ( ) )
}
2023-10-19 14:01:48 +00:00
func TestValidateSchemaMinimumCliVersionWithInvalidSemver ( t * testing . T ) {
s := & Schema {
Extension : Extension {
MinDatabricksCliVersion : "1.0.5" ,
} ,
}
err := s . validateSchemaMinimumCliVersion ( "v2.0.1" ) ( )
assert . ErrorContains ( t , err , "invalid minimum CLI version \"1.0.5\" specified. Please specify the version in the format v0.0.0" )
s . MinDatabricksCliVersion = "v1.0.5"
err = s . validateSchemaMinimumCliVersion ( "v2.0.1" ) ( )
assert . NoError ( t , err )
}
func TestValidateSchemaMinimumCliVersion ( t * testing . T ) {
s := & Schema {
Extension : Extension {
MinDatabricksCliVersion : "v1.0.5" ,
} ,
}
err := s . validateSchemaMinimumCliVersion ( "v2.0.1" ) ( )
assert . NoError ( t , err )
err = s . validateSchemaMinimumCliVersion ( "v1.0.5" ) ( )
assert . NoError ( t , err )
err = s . validateSchemaMinimumCliVersion ( "v1.0.6" ) ( )
assert . NoError ( t , err )
err = s . validateSchemaMinimumCliVersion ( "v1.0.4" ) ( )
assert . ErrorContains ( t , err , ` minimum CLI version "v1.0.5" is greater than current CLI version "v1.0.4". Please upgrade your current Databricks CLI ` )
err = s . validateSchemaMinimumCliVersion ( "v0.0.1" ) ( )
assert . ErrorContains ( t , err , "minimum CLI version \"v1.0.5\" is greater than current CLI version \"v0.0.1\". Please upgrade your current Databricks CLI" )
err = s . validateSchemaMinimumCliVersion ( "v0.0.0-dev" ) ( )
assert . NoError ( t , err )
}
2023-11-30 16:07:45 +00:00
func TestValidateSchemaConstTypes ( t * testing . T ) {
s := & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : "string" ,
Const : "abc" ,
} ,
} ,
}
err := s . validate ( )
assert . NoError ( t , err )
s = & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : "string" ,
Const : 123 ,
} ,
} ,
}
err = s . validate ( )
assert . EqualError ( t , err , "type validation for const value of property foo failed: expected type string, but value is 123" )
}
func TestValidateSchemaSkippedPropertiesHaveDefaults ( t * testing . T ) {
s := & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : "string" ,
Extension : Extension { SkipPromptIf : & Schema { } } ,
} ,
} ,
}
err := s . validate ( )
assert . EqualError ( t , err , "property \"foo\" has a skip_prompt_if clause but no default value" )
s = & Schema {
Properties : map [ string ] * Schema {
"foo" : {
Type : "string" ,
Default : "abc" ,
Extension : Extension { SkipPromptIf : & Schema { } } ,
} ,
} ,
}
err = s . validate ( )
assert . NoError ( t , err )
}
2024-04-25 11:23:50 +00:00
func testSchema ( ) * Schema {
return & Schema {
Type : "object" ,
Properties : map [ string ] * Schema {
"int_val" : {
Type : "integer" ,
Default : int64 ( 123 ) ,
} ,
"string_val" : {
Type : "string" ,
} ,
"object_val" : {
Type : "object" ,
Properties : map [ string ] * Schema {
"bar" : {
Type : "string" ,
Default : "baz" ,
} ,
} ,
AdditionalProperties : & Schema {
Type : "object" ,
Properties : map [ string ] * Schema {
"foo" : {
Type : "string" ,
Default : "zab" ,
} ,
} ,
} ,
} ,
} ,
}
}
func TestSchemaGetByPath ( t * testing . T ) {
s := testSchema ( )
ss , err := s . GetByPath ( "int_val" )
require . NoError ( t , err )
assert . Equal ( t , Schema {
Type : IntegerType ,
Default : int64 ( 123 ) ,
} , ss )
ss , err = s . GetByPath ( "string_val" )
require . NoError ( t , err )
assert . Equal ( t , Schema {
Type : StringType ,
} , ss )
ss , err = s . GetByPath ( "object_val.bar" )
require . NoError ( t , err )
assert . Equal ( t , Schema {
Type : StringType ,
Default : "baz" ,
} , ss )
ss , err = s . GetByPath ( "object_val.*.foo" )
require . NoError ( t , err )
assert . Equal ( t , Schema {
Type : StringType ,
Default : "zab" ,
} , ss )
}
func TestSchemaSetByPath ( t * testing . T ) {
s := testSchema ( )
err := s . SetByPath ( "int_val" , Schema {
Type : IntegerType ,
Default : int64 ( 456 ) ,
} )
require . NoError ( t , err )
assert . Equal ( t , int64 ( 456 ) , s . Properties [ "int_val" ] . Default )
err = s . SetByPath ( "object_val.*.foo" , Schema {
Type : StringType ,
Default : "zooby" ,
} )
require . NoError ( t , err )
ns , err := s . GetByPath ( "object_val.*.foo" )
require . NoError ( t , err )
assert . Equal ( t , Schema {
Type : StringType ,
Default : "zooby" ,
} , ns )
}