@@ -6,9 +6,11 @@ package jsonpointer
66import (
77 "encoding/json"
88 "fmt"
9+ "reflect"
910 "strconv"
1011 "testing"
1112
13+ "github.com/go-openapi/swag/jsonname"
1214 "github.com/go-openapi/testify/v2/assert"
1315 "github.com/go-openapi/testify/v2/require"
1416)
@@ -246,6 +248,7 @@ func TestPointableInterface(t *testing.T) {
246248
247249 t .Run ("with pointable type" , func (t * testing.T ) {
248250 p := & pointableImpl {"hello" }
251+
249252 result , _ , err := GetForToken (p , "some" )
250253 require .NoError (t , err )
251254 assert .Equal (t , p .a , result )
@@ -346,6 +349,95 @@ func TestArray(t *testing.T) {
346349 }
347350}
348351
352+ func TestStruct (t * testing.T ) {
353+ t .Parallel ()
354+
355+ t .Run ("with untagged struct field" , func (t * testing.T ) {
356+ type Embedded struct {
357+ D int `json:"d"`
358+ }
359+
360+ s := struct {
361+ Embedded
362+
363+ A int `json:"a"`
364+ B int
365+ Anonymous struct {
366+ C int `json:"c"`
367+ }
368+ }{}
369+
370+ {
371+ s .A = 1
372+ s .B = 2
373+ s .Anonymous .C = 3
374+ s .D = 4
375+ }
376+
377+ t .Run (`should resolve field A tagged "a"` , func (t * testing.T ) {
378+ pointerA , err := New ("/a" )
379+ require .NoError (t , err )
380+
381+ value , kind , err := pointerA .Get (s )
382+ require .NoError (t , err )
383+ require .Equal (t , reflect .Int , kind )
384+ require .Equal (t , 1 , value )
385+
386+ _ , err = pointerA .Set (& s , 9 )
387+ require .NoError (t , err )
388+
389+ value , _ , err = pointerA .Get (s )
390+ require .NoError (t , err )
391+ require .Equal (t , 9 , value )
392+ })
393+
394+ t .Run (`should resolve embedded field D with tag` , func (t * testing.T ) {
395+ pointerD , err := New ("/d" )
396+ require .NoError (t , err )
397+
398+ value , kind , err := pointerD .Get (s )
399+ require .NoError (t , err )
400+ require .Equal (t , reflect .Int , kind )
401+ require .Equal (t , 4 , value )
402+
403+ _ , err = pointerD .Set (& s , 6 )
404+ require .NoError (t , err )
405+
406+ value , _ , err = pointerD .Get (s )
407+ require .NoError (t , err )
408+ require .Equal (t , 6 , value )
409+ })
410+
411+ t .Run ("with known limitations" , func (t * testing.T ) {
412+ t .Run (`should not resolve field B without tag` , func (t * testing.T ) {
413+ pointerB , err := New ("/B" )
414+ require .NoError (t , err )
415+
416+ _ , _ , err = pointerB .Get (s )
417+ require .Error (t , err )
418+ require .ErrorContains (t , err , `has no field "B"` )
419+
420+ _ , err = pointerB .Set (& s , 8 )
421+ require .Error (t , err )
422+ require .ErrorContains (t , err , `has no field "B"` )
423+ })
424+
425+ t .Run (`should not resolve field C with tag, but anonymous` , func (t * testing.T ) {
426+ pointerC , err := New ("/c" )
427+ require .NoError (t , err )
428+
429+ _ , _ , err = pointerC .Get (s )
430+ require .Error (t , err )
431+ require .ErrorContains (t , err , `has no field "c"` )
432+
433+ _ , err = pointerC .Set (& s , 7 )
434+ require .Error (t , err )
435+ require .ErrorContains (t , err , `has no field "c"` )
436+ })
437+ })
438+ })
439+ }
440+
349441func TestOtherThings (t * testing.T ) {
350442 t .Parallel ()
351443
@@ -367,11 +459,21 @@ func TestOtherThings(t *testing.T) {
367459 })
368460
369461 t .Run ("out of bound array index should error" , func (t * testing.T ) {
370- p , err := New ("/foo/3" )
371- require .NoError (t , err )
462+ t .Run ("with index overflow" , func (t * testing.T ) {
463+ p , err := New ("/foo/3" )
464+ require .NoError (t , err )
372465
373- _ , _ , err = p .Get (testDocumentJSON (t ))
374- require .Error (t , err )
466+ _ , _ , err = p .Get (testDocumentJSON (t ))
467+ require .Error (t , err )
468+ })
469+
470+ t .Run ("with index unerflow" , func (t * testing.T ) {
471+ p , err := New ("/foo/-3" )
472+ require .NoError (t , err )
473+
474+ _ , _ , err = p .Get (testDocumentJSON (t ))
475+ require .Error (t , err )
476+ })
375477 })
376478
377479 t .Run ("referring to a key in an array should error" , func (t * testing.T ) {
@@ -907,4 +1009,101 @@ func TestEdgeCases(t *testing.T) {
9071009
9081010 require .Equal (t , doc , newDoc )
9091011 })
1012+
1013+ t .Run ("with out of bounds index" , func (t * testing.T ) {
1014+ p , err := New ("/foo/10" )
1015+ require .NoError (t , err )
1016+
1017+ t .Run ("should error on Get" , func (t * testing.T ) {
1018+ _ , _ , err := p .Get (testStructJSONDoc (t ))
1019+ require .Error (t , err )
1020+ require .ErrorContains (t , err , "index out of bounds" )
1021+ })
1022+
1023+ t .Run ("should error on Set" , func (t * testing.T ) {
1024+ _ , err := p .Set (testStructJSONPtr (t ), "peek-a-boo" )
1025+ require .Error (t , err )
1026+ require .ErrorContains (t , err , "index out of bounds" )
1027+ })
1028+ })
1029+
1030+ t .Run ("Set with invalid pointer token" , func (t * testing.T ) {
1031+ doc := testStructJSONDoc (t )
1032+ pointer , err := New ("/foo/x" )
1033+ require .NoError (t , err )
1034+
1035+ _ , err = pointer .Set (& doc , "yay" )
1036+ require .Error (t , err )
1037+ require .ErrorContains (t , err , `Atoi: parsing "x"` )
1038+ })
1039+
1040+ t .Run ("Set with invalid reference in struct" , func (t * testing.T ) {
1041+ doc := struct {
1042+ A func () `json:"a"`
1043+ B []int `json:"b"`
1044+ }{
1045+ A : func () {},
1046+ B : []int {0 , 1 },
1047+ }
1048+
1049+ t .Run ("should error when attempting to set a struct field value that is not assignable" , func (t * testing.T ) {
1050+ pointerA , err := New ("/a" )
1051+ require .NoError (t , err )
1052+
1053+ _ , err = pointerA .Set (& doc , "waou" )
1054+ require .Error (t , err )
1055+ require .ErrorContains (t , err , `can't set value with type string to field A` )
1056+ })
1057+
1058+ t .Run ("should error when attempting to set a slice element value that is not assignable" , func (t * testing.T ) {
1059+ pointerB , err := New ("/b/0" )
1060+ require .NoError (t , err )
1061+
1062+ _ , err = pointerB .Set (& doc , "waou" )
1063+ require .Error (t , err )
1064+ require .ErrorContains (t , err , `can't set value with type string to slice element 0 with type int` )
1065+ })
1066+
1067+ t .Run ("should error when attempting to set a value that does not exist" , func (t * testing.T ) {
1068+ pointerB , err := New ("/x" )
1069+ require .NoError (t , err )
1070+
1071+ _ , _ , err = pointerB .Get (& doc )
1072+ require .Error (t , err )
1073+ require .ErrorContains (t , err , `no field` )
1074+
1075+ _ , err = pointerB .Set (& doc , "oops" )
1076+ require .Error (t , err )
1077+ require .ErrorContains (t , err , `no field` )
1078+ })
1079+ })
1080+ }
1081+
1082+ func TestInternalEdgeCases (t * testing.T ) {
1083+ t .Parallel ()
1084+
1085+ t .Run ("setSingleImpl should error on any node not a struct, map or slice" , func (t * testing.T ) {
1086+ var node int
1087+
1088+ err := setSingleImpl (& node , 3 , "a" , jsonname .DefaultJSONNameProvider )
1089+ require .Error (t , err )
1090+ require .ErrorContains (t , err , `invalid token reference "a"` )
1091+ })
1092+
1093+ t .Run ("with simulated unsettable" , func (t * testing.T ) {
1094+ type unsettable struct {
1095+ A string `json:"a"`
1096+ }
1097+ doc := unsettable {
1098+ A : "a" ,
1099+ }
1100+
1101+ t .Run ("setSingleImpl should error on struct field that is not settable" , func (t * testing.T ) {
1102+ node := doc // doesn't pass a pointer: unsettable
1103+
1104+ err := setSingleImpl (node , "new value" , "a" , jsonname .DefaultJSONNameProvider )
1105+ require .Error (t , err )
1106+ require .ErrorContains (t , err , `can't set struct field` )
1107+ })
1108+ })
9101109}
0 commit comments