@@ -6,6 +6,7 @@ package jsonpointer
66import (
77 "encoding/json"
88 "fmt"
9+ "reflect"
910 "strconv"
1011 "testing"
1112
@@ -246,6 +247,7 @@ func TestPointableInterface(t *testing.T) {
246247
247248 t .Run ("with pointable type" , func (t * testing.T ) {
248249 p := & pointableImpl {"hello" }
250+
249251 result , _ , err := GetForToken (p , "some" )
250252 require .NoError (t , err )
251253 assert .Equal (t , p .a , result )
@@ -346,6 +348,95 @@ func TestArray(t *testing.T) {
346348 }
347349}
348350
351+ func TestStruct (t * testing.T ) {
352+ t .Parallel ()
353+
354+ t .Run ("with untagged struct field" , func (t * testing.T ) {
355+ type Embedded struct {
356+ D int `json:"d"`
357+ }
358+
359+ s := struct {
360+ Embedded
361+
362+ A int `json:"a"`
363+ B int
364+ Anonymous struct {
365+ C int `json:"c"`
366+ }
367+ }{}
368+
369+ {
370+ s .A = 1
371+ s .B = 2
372+ s .Anonymous .C = 3
373+ s .D = 4
374+ }
375+
376+ t .Run (`should resolve field A tagged "a"` , func (t * testing.T ) {
377+ pointerA , err := New ("/a" )
378+ require .NoError (t , err )
379+
380+ value , kind , err := pointerA .Get (s )
381+ require .NoError (t , err )
382+ require .Equal (t , reflect .Int , kind )
383+ require .Equal (t , 1 , value )
384+
385+ _ , err = pointerA .Set (& s , 9 )
386+ require .NoError (t , err )
387+
388+ value , _ , err = pointerA .Get (s )
389+ require .NoError (t , err )
390+ require .Equal (t , 9 , value )
391+ })
392+
393+ t .Run (`should resolve embedded field D with tag` , func (t * testing.T ) {
394+ pointerD , err := New ("/d" )
395+ require .NoError (t , err )
396+
397+ value , kind , err := pointerD .Get (s )
398+ require .NoError (t , err )
399+ require .Equal (t , reflect .Int , kind )
400+ require .Equal (t , 4 , value )
401+
402+ _ , err = pointerD .Set (& s , 6 )
403+ require .NoError (t , err )
404+
405+ value , _ , err = pointerD .Get (s )
406+ require .NoError (t , err )
407+ require .Equal (t , 6 , value )
408+ })
409+
410+ t .Run ("with known limitations" , func (t * testing.T ) {
411+ t .Run (`should not resolve field B without tag` , func (t * testing.T ) {
412+ pointerB , err := New ("/B" )
413+ require .NoError (t , err )
414+
415+ _ , _ , err = pointerB .Get (s )
416+ require .Error (t , err )
417+ require .ErrorContains (t , err , `has no field "B"` )
418+
419+ _ , err = pointerB .Set (& s , 8 )
420+ require .Error (t , err )
421+ require .ErrorContains (t , err , `has no field "B"` )
422+ })
423+
424+ t .Run (`should not resolve field C with tag, but anonymous` , func (t * testing.T ) {
425+ pointerC , err := New ("/c" )
426+ require .NoError (t , err )
427+
428+ _ , _ , err = pointerC .Get (s )
429+ require .Error (t , err )
430+ require .ErrorContains (t , err , `has no field "c"` )
431+
432+ _ , err = pointerC .Set (& s , 7 )
433+ require .Error (t , err )
434+ require .ErrorContains (t , err , `has no field "c"` )
435+ })
436+ })
437+ })
438+ }
439+
349440func TestOtherThings (t * testing.T ) {
350441 t .Parallel ()
351442
@@ -367,11 +458,21 @@ func TestOtherThings(t *testing.T) {
367458 })
368459
369460 t .Run ("out of bound array index should error" , func (t * testing.T ) {
370- p , err := New ("/foo/3" )
371- require .NoError (t , err )
461+ t .Run ("with index overflow" , func (t * testing.T ) {
462+ p , err := New ("/foo/3" )
463+ require .NoError (t , err )
372464
373- _ , _ , err = p .Get (testDocumentJSON (t ))
374- require .Error (t , err )
465+ _ , _ , err = p .Get (testDocumentJSON (t ))
466+ require .Error (t , err )
467+ })
468+
469+ t .Run ("with index unerflow" , func (t * testing.T ) {
470+ p , err := New ("/foo/-3" )
471+ require .NoError (t , err )
472+
473+ _ , _ , err = p .Get (testDocumentJSON (t ))
474+ require .Error (t , err )
475+ })
375476 })
376477
377478 t .Run ("referring to a key in an array should error" , func (t * testing.T ) {
@@ -907,4 +1008,72 @@ func TestEdgeCases(t *testing.T) {
9071008
9081009 require .Equal (t , doc , newDoc )
9091010 })
1011+
1012+ t .Run ("with out of bounds index" , func (t * testing.T ) {
1013+ p , err := New ("/foo/10" )
1014+ require .NoError (t , err )
1015+
1016+ t .Run ("should error on Get" , func (t * testing.T ) {
1017+ _ , _ , err := p .Get (testStructJSONDoc (t ))
1018+ require .Error (t , err )
1019+ require .ErrorContains (t , err , "index out of bounds" )
1020+ })
1021+
1022+ t .Run ("should error on Set" , func (t * testing.T ) {
1023+ _ , err := p .Set (testStructJSONPtr (t ), "peek-a-boo" )
1024+ require .Error (t , err )
1025+ require .ErrorContains (t , err , "index out of bounds" )
1026+ })
1027+ })
1028+
1029+ t .Run ("Set with invalid pointer token" , func (t * testing.T ) {
1030+ doc := testStructJSONDoc (t )
1031+ pointer , err := New ("/foo/x" )
1032+ require .NoError (t , err )
1033+
1034+ _ , err = pointer .Set (& doc , "yay" )
1035+ require .Error (t , err )
1036+ require .ErrorContains (t , err , `Atoi: parsing "x"` )
1037+ })
1038+
1039+ t .Run ("Set with invalid reference in struct" , func (t * testing.T ) {
1040+ doc := struct {
1041+ A func () `json:"a"`
1042+ B []int `json:"b"`
1043+ }{
1044+ A : func () {},
1045+ B : []int {0 , 1 },
1046+ }
1047+
1048+ t .Run ("should error when attempting to set a struct field value that is not assignable" , func (t * testing.T ) {
1049+ pointerA , err := New ("/a" )
1050+ require .NoError (t , err )
1051+
1052+ _ , err = pointerA .Set (& doc , "waou" )
1053+ require .Error (t , err )
1054+ require .ErrorContains (t , err , `can't set value with type string to field A` )
1055+ })
1056+
1057+ t .Run ("should error when attempting to set a slice element value that is not assignable" , func (t * testing.T ) {
1058+ pointerB , err := New ("/b/0" )
1059+ require .NoError (t , err )
1060+
1061+ _ , err = pointerB .Set (& doc , "waou" )
1062+ require .Error (t , err )
1063+ require .ErrorContains (t , err , `can't set value with type string to slice element 0 with type int` )
1064+ })
1065+
1066+ t .Run ("should error when attempting to set a value that does not exist" , func (t * testing.T ) {
1067+ pointerB , err := New ("/x" )
1068+ require .NoError (t , err )
1069+
1070+ _ , _ , err = pointerB .Get (& doc )
1071+ require .Error (t , err )
1072+ require .ErrorContains (t , err , `no field` )
1073+
1074+ _ , err = pointerB .Set (& doc , "oops" )
1075+ require .Error (t , err )
1076+ require .ErrorContains (t , err , `no field` )
1077+ })
1078+ })
9101079}
0 commit comments