Skip to content

Commit 990c305

Browse files
authored
Merge pull request #370 from civist/nil-pointer-safety
Enum nil pointer safety
2 parents a13937c + 6b054a4 commit 990c305

File tree

4 files changed

+131
-1
lines changed

4 files changed

+131
-1
lines changed

definition.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,10 @@ func (gt *Enum) Values() []*EnumValueDefinition {
964964
}
965965
func (gt *Enum) Serialize(value interface{}) interface{} {
966966
v := value
967-
if reflect.ValueOf(v).Kind() == reflect.Ptr {
967+
rv := reflect.ValueOf(v)
968+
if kind := rv.Kind(); kind == reflect.Ptr && rv.IsNil() {
969+
return nil
970+
} else if kind == reflect.Ptr {
968971
v = reflect.Indirect(reflect.ValueOf(v)).Interface()
969972
}
970973
if enumValue, ok := gt.getValueLookup()[v]; ok {

enum_type_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,3 +421,42 @@ func TestTypeSystem_EnumValues_EnumValueMayBePointer(t *testing.T) {
421421
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, result))
422422
}
423423
}
424+
425+
func TestTypeSystem_EnumValues_EnumValueMayBeNilPointer(t *testing.T) {
426+
var enumTypeTestSchema, _ = graphql.NewSchema(graphql.SchemaConfig{
427+
Query: graphql.NewObject(graphql.ObjectConfig{
428+
Name: "Query",
429+
Fields: graphql.Fields{
430+
"query": &graphql.Field{
431+
Type: graphql.NewObject(graphql.ObjectConfig{
432+
Name: "query",
433+
Fields: graphql.Fields{
434+
"color": &graphql.Field{
435+
Type: enumTypeTestColorType,
436+
},
437+
},
438+
}),
439+
Resolve: func(_ graphql.ResolveParams) (interface{}, error) {
440+
return struct {
441+
Color *int `graphql:"color"`
442+
}{nil}, nil
443+
},
444+
},
445+
},
446+
}),
447+
})
448+
query := "{ query { color } }"
449+
expected := &graphql.Result{
450+
Data: map[string]interface{}{
451+
"query": map[string]interface{}{
452+
"color": nil,
453+
}},
454+
}
455+
result := g(t, graphql.Params{
456+
Schema: enumTypeTestSchema,
457+
RequestString: query,
458+
})
459+
if !reflect.DeepEqual(expected, result) {
460+
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, result))
461+
}
462+
}

lists_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,3 +870,32 @@ func TestLists_ArrayOfNullableObjects_ContainsValues(t *testing.T) {
870870
}
871871
checkList(t, ttype, data, expected)
872872
}
873+
874+
func TestLists_ValueMayBeNilPointer(t *testing.T) {
875+
var listTestSchema, _ = graphql.NewSchema(graphql.SchemaConfig{
876+
Query: graphql.NewObject(graphql.ObjectConfig{
877+
Name: "Query",
878+
Fields: graphql.Fields{
879+
"list": &graphql.Field{
880+
Type: graphql.NewList(graphql.Int),
881+
Resolve: func(_ graphql.ResolveParams) (interface{}, error) {
882+
return []int(nil), nil
883+
},
884+
},
885+
},
886+
}),
887+
})
888+
query := "{ list }"
889+
expected := &graphql.Result{
890+
Data: map[string]interface{}{
891+
"list": []interface{}{},
892+
},
893+
}
894+
result := g(t, graphql.Params{
895+
Schema: listTestSchema,
896+
RequestString: query,
897+
})
898+
if !reflect.DeepEqual(expected, result) {
899+
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, result))
900+
}
901+
}

union_interface_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,3 +585,62 @@ func TestUnionIntersectionTypes_GetsExecutionInfoInResolver(t *testing.T) {
585585
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(schema2, encounteredSchema))
586586
}
587587
}
588+
589+
func TestUnionIntersectionTypes_ValueMayBeNilPointer(t *testing.T) {
590+
var unionInterfaceTestSchema, _ = graphql.NewSchema(graphql.SchemaConfig{
591+
Query: graphql.NewObject(graphql.ObjectConfig{
592+
Name: "Query",
593+
Fields: graphql.Fields{
594+
"query": &graphql.Field{
595+
Type: graphql.NewObject(graphql.ObjectConfig{
596+
Name: "query",
597+
Fields: graphql.Fields{
598+
"pet": &graphql.Field{
599+
Type: petType,
600+
},
601+
"named": &graphql.Field{
602+
Type: namedType,
603+
},
604+
},
605+
}),
606+
Resolve: func(_ graphql.ResolveParams) (interface{}, error) {
607+
return struct {
608+
Pet *testCat2 `graphql:"pet"`
609+
Named *testCat2 `graphql:"named"`
610+
}{nil, nil}, nil
611+
},
612+
},
613+
},
614+
}),
615+
})
616+
query := `{
617+
query {
618+
pet {
619+
__typename
620+
}
621+
named {
622+
__typename
623+
name
624+
}
625+
}
626+
}`
627+
expected := &graphql.Result{
628+
Data: map[string]interface{}{
629+
"query": map[string]interface{}{
630+
"pet": map[string]interface{}{
631+
"__typename": "Cat",
632+
},
633+
"named": map[string]interface{}{
634+
"__typename": "Cat",
635+
"name": nil,
636+
},
637+
}},
638+
}
639+
result := g(t, graphql.Params{
640+
Schema: unionInterfaceTestSchema,
641+
RequestString: query,
642+
})
643+
if !reflect.DeepEqual(expected, result) {
644+
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, result))
645+
}
646+
}

0 commit comments

Comments
 (0)