mirror of https://github.com/databricks/cli.git
Moved tracing to safeToSchema
This commit is contained in:
parent
35d9829b7b
commit
5da5ea0c7a
|
@ -73,7 +73,7 @@ type Schema struct {
|
||||||
func NewSchema(golangType reflect.Type, docs *Docs) (*Schema, error) {
|
func NewSchema(golangType reflect.Type, docs *Docs) (*Schema, error) {
|
||||||
seenTypes := map[reflect.Type]struct{}{}
|
seenTypes := map[reflect.Type]struct{}{}
|
||||||
debugTrace := list.New()
|
debugTrace := list.New()
|
||||||
schema, err := toSchema(golangType, docs, seenTypes, debugTrace)
|
schema, err := safeToSchema(golangType, docs, "", seenTypes, debugTrace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errWithTrace(err.Error(), debugTrace)
|
return nil, errWithTrace(err.Error(), debugTrace)
|
||||||
}
|
}
|
||||||
|
@ -120,14 +120,16 @@ func errWithTrace(prefix string, trace *list.List) error {
|
||||||
traceString := "root"
|
traceString := "root"
|
||||||
curr := trace.Front()
|
curr := trace.Front()
|
||||||
for curr != nil {
|
for curr != nil {
|
||||||
traceString += " -> " + curr.Value.(string)
|
if curr.Value.(string) != "" {
|
||||||
|
traceString += " -> " + curr.Value.(string)
|
||||||
|
}
|
||||||
curr = curr.Next()
|
curr = curr.Next()
|
||||||
}
|
}
|
||||||
return fmt.Errorf("[ERROR] " + prefix + ". traversal trace: " + traceString)
|
return fmt.Errorf("[ERROR] " + prefix + ". traversal trace: " + traceString)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A wrapper over toSchema function to detect cycles in the bundle config struct
|
// A wrapper over toSchema function to detect cycles in the bundle config struct
|
||||||
func safeToSchema(golangType reflect.Type, docs *Docs, seenTypes map[reflect.Type]struct{}, debugTrace *list.List) (*Schema, error) {
|
func safeToSchema(golangType reflect.Type, docs *Docs, debugTraceId string, seenTypes map[reflect.Type]struct{}, debugTrace *list.List) (*Schema, error) {
|
||||||
// WE ERROR OUT IF THERE ARE CYCLES IN THE JSON SCHEMA
|
// WE ERROR OUT IF THERE ARE CYCLES IN THE JSON SCHEMA
|
||||||
// There are mechanisms to deal with cycles though recursive identifiers in json
|
// There are mechanisms to deal with cycles though recursive identifiers in json
|
||||||
// schema. However if we use them, we would need to make sure we are able to detect
|
// schema. However if we use them, we would need to make sure we are able to detect
|
||||||
|
@ -140,12 +142,18 @@ func safeToSchema(golangType reflect.Type, docs *Docs, seenTypes map[reflect.Typ
|
||||||
fmt.Println("[DEBUG] traceSet: ", seenTypes)
|
fmt.Println("[DEBUG] traceSet: ", seenTypes)
|
||||||
return nil, fmt.Errorf("cycle detected")
|
return nil, fmt.Errorf("cycle detected")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update set of types in current path
|
// Update set of types in current path
|
||||||
seenTypes[golangType] = struct{}{}
|
seenTypes[golangType] = struct{}{}
|
||||||
|
|
||||||
|
// Add the json tag name of struct field to debug trace
|
||||||
|
debugTrace.PushBack(debugTraceId)
|
||||||
props, err := toSchema(golangType, docs, seenTypes, debugTrace)
|
props, err := toSchema(golangType, docs, seenTypes, debugTrace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
back := debugTrace.Back()
|
||||||
|
debugTrace.Remove(back)
|
||||||
delete(seenTypes, golangType)
|
delete(seenTypes, golangType)
|
||||||
return props, nil
|
return props, nil
|
||||||
}
|
}
|
||||||
|
@ -194,7 +202,7 @@ func addStructFields(fields []reflect.StructField, golangType reflect.Type) []re
|
||||||
func toSchema(golangType reflect.Type, docs *Docs, seenTypes map[reflect.Type]struct{}, debugTrace *list.List) (*Schema, error) {
|
func toSchema(golangType reflect.Type, docs *Docs, seenTypes map[reflect.Type]struct{}, debugTrace *list.List) (*Schema, error) {
|
||||||
// *Struct and Struct generate identical json schemas
|
// *Struct and Struct generate identical json schemas
|
||||||
if golangType.Kind() == reflect.Pointer {
|
if golangType.Kind() == reflect.Pointer {
|
||||||
return toSchema(golangType.Elem(), docs, seenTypes, debugTrace)
|
return safeToSchema(golangType.Elem(), docs, "", seenTypes, debugTrace)
|
||||||
}
|
}
|
||||||
|
|
||||||
if golangType.Kind() == reflect.Interface {
|
if golangType.Kind() == reflect.Interface {
|
||||||
|
@ -219,7 +227,7 @@ func toSchema(golangType reflect.Type, docs *Docs, seenTypes map[reflect.Type]st
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
elemProps, err := safeToSchema(elemGolangType, docs, seenTypes, debugTrace)
|
elemProps, err := safeToSchema(elemGolangType, docs, "", seenTypes, debugTrace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -238,7 +246,7 @@ func toSchema(golangType reflect.Type, docs *Docs, seenTypes map[reflect.Type]st
|
||||||
if golangType.Key().Kind() != reflect.String {
|
if golangType.Key().Kind() != reflect.String {
|
||||||
return nil, fmt.Errorf("only string keyed maps allowed")
|
return nil, fmt.Errorf("only string keyed maps allowed")
|
||||||
}
|
}
|
||||||
additionalProperties, err = safeToSchema(golangType.Elem(), docs, seenTypes, debugTrace)
|
additionalProperties, err = safeToSchema(golangType.Elem(), docs, "", seenTypes, debugTrace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -282,14 +290,11 @@ func toSchema(golangType reflect.Type, docs *Docs, seenTypes map[reflect.Type]st
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute Schema.Properties for the child recursively
|
// compute Schema.Properties for the child recursively
|
||||||
debugTrace.PushBack(childName)
|
fieldProps, err := safeToSchema(child.Type, childDocs, childName, seenTypes, debugTrace)
|
||||||
fieldProps, err := safeToSchema(child.Type, childDocs, seenTypes, debugTrace)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
properties[childName] = fieldProps
|
properties[childName] = fieldProps
|
||||||
back := debugTrace.Back()
|
|
||||||
debugTrace.Remove(back)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set Schema.AdditionalProperties to false
|
// set Schema.AdditionalProperties to false
|
||||||
|
|
|
@ -1133,7 +1133,7 @@ func TestErrorIfStructRefersToItself(t *testing.T) {
|
||||||
|
|
||||||
elem := Foo{}
|
elem := Foo{}
|
||||||
_, err := NewSchema(reflect.TypeOf(elem), nil)
|
_, err := NewSchema(reflect.TypeOf(elem), nil)
|
||||||
assert.ErrorContains(t, err, "ERROR] cycle detected. traversal trace: root -> my_foo -> my_foo")
|
assert.ErrorContains(t, err, "ERROR] cycle detected. traversal trace: root -> my_foo")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestErrorIfStructHasLoop(t *testing.T) {
|
func TestErrorIfStructHasLoop(t *testing.T) {
|
||||||
|
@ -1150,7 +1150,7 @@ func TestErrorIfStructHasLoop(t *testing.T) {
|
||||||
|
|
||||||
elem := Apple{}
|
elem := Apple{}
|
||||||
_, err := NewSchema(reflect.TypeOf(elem), nil)
|
_, err := NewSchema(reflect.TypeOf(elem), nil)
|
||||||
assert.ErrorContains(t, err, "[ERROR] cycle detected. traversal trace: root -> my_mango -> my_guava -> my_papaya -> my_apple -> my_mango")
|
assert.ErrorContains(t, err, "[ERROR] cycle detected. traversal trace: root -> my_mango -> my_guava -> my_papaya -> my_apple")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInterfaceGeneratesEmptySchema(t *testing.T) {
|
func TestInterfaceGeneratesEmptySchema(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue