databricks-cli/bundle/schema/schema_test.go

435 lines
8.3 KiB
Go

package schema
import (
"container/list"
"encoding/json"
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// TODO: add tests to assert that these are valid json schemas. Maybe validate some
// json/yaml documents againts them, by unmarshalling a value
func TestNumberStringBooleanSchema(t *testing.T) {
type Foo struct {
IntVal int `json:"int_val"`
Int8Val int8 `json:"int8_val"`
Int16Val int16 `json:"int16_val"`
Int32Val int32 `json:"int32_val"`
Int64Val int64 `json:"int64_val"`
Uint8Val int8 `json:"uint8_val"`
Uint16Val int16 `json:"uint16_val"`
Uint32Val int32 `json:"uint32_val"`
Uint64Val int64 `json:"uint64_val"`
Float32Val int64 `json:"float32_val"`
Float64Val int64 `json:"float64_val"`
StringVal string `json:"string_val"`
BoolVal string `json:"bool_val"`
}
elem := Foo{}
schema, err := NewSchema(reflect.TypeOf(elem))
assert.NoError(t, err)
jsonSchema, err := json.MarshalIndent(schema, " ", " ")
assert.NoError(t, err)
expected :=
`{
"type": "object",
"properties": {
"bool_val": {
"type": "string"
},
"float32_val": {
"type": "number"
},
"float64_val": {
"type": "number"
},
"int16_val": {
"type": "number"
},
"int32_val": {
"type": "number"
},
"int64_val": {
"type": "number"
},
"int8_val": {
"type": "number"
},
"int_val": {
"type": "number"
},
"string_val": {
"type": "string"
},
"uint16_val": {
"type": "number"
},
"uint32_val": {
"type": "number"
},
"uint64_val": {
"type": "number"
},
"uint8_val": {
"type": "number"
}
}
}`
t.Log("[DEBUG] actual: ", string(jsonSchema))
t.Log("[DEBUG] expected: ", expected)
assert.Equal(t, expected, string(jsonSchema))
}
func TestObjectSchema(t *testing.T) {
type Person struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
}
type Plot struct {
Stakes []string `json:"stakes"`
}
type Story struct {
Hero Person `json:"hero"`
Villian Person `json:"villian"`
Plot Plot `json:"plot"`
}
elem := Story{}
schema, err := NewSchema(reflect.TypeOf(elem))
assert.NoError(t, err)
jsonSchema, err := json.MarshalIndent(schema, " ", " ")
assert.NoError(t, err)
expected :=
`{
"type": "object",
"properties": {
"hero": {
"type": "object",
"properties": {
"age": {
"type": "number"
},
"name": {
"type": "string"
}
}
},
"plot": {
"type": "object",
"properties": {
"stakes": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"villian": {
"type": "object",
"properties": {
"age": {
"type": "number"
},
"name": {
"type": "string"
}
}
}
}
}`
t.Log("[DEBUG] actual: ", string(jsonSchema))
t.Log("[DEBUG] expected: ", expected)
assert.Equal(t, expected, string(jsonSchema))
}
func TestSliceOfObjectsSchema(t *testing.T) {
type Person struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
}
type Plot struct {
MainCharacters []Person `json:"main_characters"`
}
type Story struct {
Plot Plot `json:"plot"`
}
elem := Story{}
schema, err := NewSchema(reflect.TypeOf(elem))
assert.NoError(t, err)
jsonSchema, err := json.MarshalIndent(schema, " ", " ")
assert.NoError(t, err)
expected :=
`{
"type": "object",
"properties": {
"plot": {
"type": "object",
"properties": {
"main_characters": {
"type": "array",
"items": {
"type": "object",
"properties": {
"age": {
"type": "number"
},
"name": {
"type": "string"
}
}
}
}
}
}
}
}`
t.Log("[DEBUG] actual: ", string(jsonSchema))
t.Log("[DEBUG] expected: ", expected)
assert.Equal(t, expected, string(jsonSchema))
}
func TestMapOfObjectsSchema(t *testing.T) {
type Person struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
}
type Plot struct {
Events map[string]Person `json:"events"`
}
type Story struct {
Plot Plot `json:"plot"`
}
elem := Story{}
schema, err := NewSchema(reflect.TypeOf(elem))
assert.NoError(t, err)
jsonSchema, err := json.MarshalIndent(schema, " ", " ")
assert.NoError(t, err)
expected :=
`{
"type": "object",
"properties": {
"plot": {
"type": "object",
"properties": {
"events": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"age": {
"type": "number"
},
"name": {
"type": "string"
}
}
}
}
}
}
}
}`
t.Log("[DEBUG] actual: ", string(jsonSchema))
t.Log("[DEBUG] expected: ", expected)
assert.Equal(t, expected, string(jsonSchema))
}
func TestEmbeddedStructSchema(t *testing.T) {
type Person struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
}
type Location struct {
Country string `json:"country"`
State string `json:"state,omitempty"`
}
type Plot struct {
Events map[string]Person `json:"events"`
}
type Story struct {
Plot Plot `json:"plot"`
*Person
Location
}
elem := Story{}
schema, err := NewSchema(reflect.TypeOf(elem))
assert.NoError(t, err)
jsonSchema, err := json.MarshalIndent(schema, " ", " ")
assert.NoError(t, err)
expected :=
`{
"type": "object",
"properties": {
"age": {
"type": "number"
},
"country": {
"type": "string"
},
"name": {
"type": "string"
},
"plot": {
"type": "object",
"properties": {
"events": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"age": {
"type": "number"
},
"name": {
"type": "string"
}
}
}
}
}
},
"state": {
"type": "string"
}
}
}`
t.Log("[DEBUG] actual: ", string(jsonSchema))
t.Log("[DEBUG] expected: ", expected)
assert.Equal(t, expected, string(jsonSchema))
}
func TestErrorWithTrace(t *testing.T) {
debugTrace := list.New()
err := errWithTrace("with empty trace", debugTrace)
assert.ErrorContains(t, err, "[ERROR] with empty trace. traversal trace: root")
debugTrace.PushBack("resources")
err = errWithTrace("with depth = 1", debugTrace)
assert.ErrorContains(t, err, "[ERROR] with depth = 1. traversal trace: root -> resources")
debugTrace.PushBack("pipelines")
debugTrace.PushBack("datasets")
err = errWithTrace("with depth = 4", debugTrace)
assert.ErrorContains(t, err, "[ERROR] with depth = 4. traversal trace: root -> resources -> pipelines -> datasets")
}
func TestNonAnnotatedFieldsAreSkipped(t *testing.T) {
type MyStruct struct {
Foo string
Bar int `json:"bar"`
}
elem := MyStruct{}
schema, err := NewSchema(reflect.TypeOf(elem))
require.NoError(t, err)
jsonSchema, err := json.MarshalIndent(schema, " ", " ")
assert.NoError(t, err)
expectedSchema :=
`{
"type": "object",
"properties": {
"bar": {
"type": "number"
}
}
}`
t.Log("[DEBUG] actual: ", string(jsonSchema))
t.Log("[DEBUG] expected: ", expectedSchema)
assert.Equal(t, expectedSchema, string(jsonSchema))
}
func TestDashFieldsAreSkipped(t *testing.T) {
type MyStruct struct {
Foo string `json:"-"`
Bar int `json:"bar"`
}
elem := MyStruct{}
schema, err := NewSchema(reflect.TypeOf(elem))
require.NoError(t, err)
jsonSchema, err := json.MarshalIndent(schema, " ", " ")
assert.NoError(t, err)
expectedSchema :=
`{
"type": "object",
"properties": {
"bar": {
"type": "number"
}
}
}`
t.Log("[DEBUG] actual: ", string(jsonSchema))
t.Log("[DEBUG] expected: ", expectedSchema)
assert.Equal(t, expectedSchema, string(jsonSchema))
}
// // Only for testing bundle, will be removed
// func TestBundleSchema(t *testing.T) {
// elem := config.Root{}
// schema, err := NewSchema(reflect.TypeOf(elem))
// assert.NoError(t, err)
// jsonSchema, err := json.MarshalIndent(schema, " ", " ")
// assert.NoError(t, err)
// expected :=
// ``
// t.Log("[DEBUG] actual: ", string(jsonSchema))
// t.Log("[DEBUG] expected: ", expected)
// assert.Equal(t, expected, string(jsonSchema))
// }