Skip to content

Commit f0ac935

Browse files
committed
Merge pull request #47 from pendo-io/improve-tests
Improved test code and added Parse* tests
2 parents cdf1f9b + 2c75d2b commit f0ac935

File tree

1 file changed

+201
-51
lines changed

1 file changed

+201
-51
lines changed

parser_test.go

Lines changed: 201 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -199,55 +199,48 @@ var getTests = []GetTest{
199199

200200
// Not found key tests
201201
GetTest{
202-
desc: "non-existent key 1",
203-
json: `{"a":"b"}`,
204-
path: []string{"c"},
205-
isFound: false,
206-
isErr: true,
202+
desc: "non-existent key 1",
203+
json: `{"a":"b"}`,
204+
path: []string{"c"},
205+
isErr: true,
207206
},
208207
GetTest{
209-
desc: "non-existent key 2",
210-
json: `{"a":"b"}`,
211-
path: []string{"b"},
212-
isFound: false,
213-
isErr: true,
208+
desc: "non-existent key 2",
209+
json: `{"a":"b"}`,
210+
path: []string{"b"},
211+
isErr: true,
214212
},
215213
GetTest{
216-
desc: "non-existent key 3",
217-
json: `{"aa":"b"}`,
218-
path: []string{"a"},
219-
isFound: false,
220-
isErr: true,
214+
desc: "non-existent key 3",
215+
json: `{"aa":"b"}`,
216+
path: []string{"a"},
217+
isErr: true,
221218
},
222219
GetTest{
223-
desc: "apply scope of parent when search for nested key",
224-
json: `{"a": { "b": 1}, "c": 2 }`,
225-
path: []string{"a", "b", "c"},
226-
isFound: false,
227-
isErr: true,
220+
desc: "apply scope of parent when search for nested key",
221+
json: `{"a": { "b": 1}, "c": 2 }`,
222+
path: []string{"a", "b", "c"},
223+
isErr: true,
228224
},
229225
GetTest{
230-
desc: `apply scope to key level`,
231-
json: `{"a": { "b": 1}, "c": 2 }`,
232-
path: []string{"b"},
233-
isFound: false,
234-
isErr: true,
226+
desc: `apply scope to key level`,
227+
json: `{"a": { "b": 1}, "c": 2 }`,
228+
path: []string{"b"},
229+
isErr: true,
235230
},
236231
GetTest{
237-
desc: `handle escaped quote in key name in JSON`,
238-
json: `{"key\"key": 1}`,
239-
path: []string{"key"},
240-
isFound: false,
241-
isErr: true,
232+
desc: `handle escaped quote in key name in JSON`,
233+
json: `{"key\"key": 1}`,
234+
path: []string{"key"},
235+
isErr: true,
242236
},
243237

244238
// Error/invalid tests
245239
GetTest{
246-
desc: `handle escaped quote in key name in JSON`,
247-
json: `{"key\"key": 1}`,
248-
path: []string{"key"},
249-
isFound: false,
250-
isErr: true,
240+
desc: `handle escaped quote in key name in JSON`,
241+
json: `{"key\"key": 1}`,
242+
path: []string{"key"},
243+
isErr: true,
251244
},
252245
GetTest{
253246
desc: `missing closing brace, but can still find key`,
@@ -463,8 +456,8 @@ var getArrayTests = []GetTest{
463456

464457
// checkFoundAndNoError checks the dataType and error return from Get*() against the test case expectations.
465458
// Returns true the test should proceed to checking the actual data returned from Get*(), or false if the test is finished.
466-
func checkFoundAndNoError(t *testing.T, testKind string, test GetTest, jtype ValueType, value interface{}, err error) bool {
467-
isFound := (jtype != NotExist)
459+
func getTestCheckFoundAndNoError(t *testing.T, testKind string, test GetTest, jtype ValueType, value interface{}, err error) bool {
460+
isFound := (jtype != NotExist) && (err != KeyPathNotFoundError)
468461
isErr := (err != nil)
469462

470463
if test.isErr != isErr {
@@ -478,10 +471,6 @@ func checkFoundAndNoError(t *testing.T, testKind string, test GetTest, jtype Val
478471
// Else, if the call didn't match the is-found expectation, fail
479472
t.Errorf("%s test '%s' isFound mismatch: expected %t, obtained %t", testKind, test.desc, test.isFound, isFound)
480473
return false
481-
} else if !isFound && err != KeyPathNotFoundError {
482-
// Else, if no value was found and the error is not correct, fail
483-
t.Errorf("%s test '%s' error mismatch: expected %t, obtained %t", testKind, test.desc, KeyPathNotFoundError, err)
484-
return false
485474
} else if !isFound {
486475
// Else, if no value was found, don't fail and don't check the value
487476
return false
@@ -491,7 +480,7 @@ func checkFoundAndNoError(t *testing.T, testKind string, test GetTest, jtype Val
491480
}
492481
}
493482

494-
func runTests(t *testing.T, tests []GetTest, runner func(GetTest) (interface{}, ValueType, error), typeChecker func(GetTest, interface{}) (bool, interface{})) {
483+
func runGetTests(t *testing.T, testKind string, tests []GetTest, runner func(GetTest) (interface{}, ValueType, error), resultChecker func(GetTest, interface{}) (bool, interface{})) {
495484
for _, test := range tests {
496485
if activeTest != "" && test.desc != activeTest {
497486
continue
@@ -501,27 +490,27 @@ func runTests(t *testing.T, tests []GetTest, runner func(GetTest) (interface{},
501490

502491
value, dataType, err := runner(test)
503492

504-
if checkFoundAndNoError(t, "Get()", test, dataType, value, err) {
493+
if getTestCheckFoundAndNoError(t, testKind, test, dataType, value, err) {
505494
if test.data == nil {
506495
t.Errorf("MALFORMED TEST: %v", test)
507496
continue
508497
}
509498

510-
if ok, expected := typeChecker(test, value); !ok {
499+
if ok, expected := resultChecker(test, value); !ok {
511500
if expectedBytes, ok := expected.([]byte); ok {
512501
expected = string(expectedBytes)
513502
}
514503
if valueBytes, ok := value.([]byte); ok {
515504
value = string(valueBytes)
516505
}
517-
t.Errorf("Test '%s' expected to return value %v, but did returned %v instead", test.desc, expected, value)
506+
t.Errorf("%s test '%s' expected to return value %v, but did returned %v instead", testKind, test.desc, expected, value)
518507
}
519508
}
520509
}
521510
}
522511

523512
func TestGet(t *testing.T) {
524-
runTests(t, getTests,
513+
runGetTests(t, "Get()", getTests,
525514
func(test GetTest) (value interface{}, dataType ValueType, err error) {
526515
value, dataType, _, err = Get([]byte(test.json), test.path...)
527516
return
@@ -534,7 +523,7 @@ func TestGet(t *testing.T) {
534523
}
535524

536525
func TestGetString(t *testing.T) {
537-
runTests(t, getStringTests,
526+
runGetTests(t, "GetString()", getStringTests,
538527
func(test GetTest) (value interface{}, dataType ValueType, err error) {
539528
value, err = GetString([]byte(test.json), test.path...)
540529
return value, String, err
@@ -547,7 +536,7 @@ func TestGetString(t *testing.T) {
547536
}
548537

549538
func TestGetInt(t *testing.T) {
550-
runTests(t, getIntTests,
539+
runGetTests(t, "GetInt()", getIntTests,
551540
func(test GetTest) (value interface{}, dataType ValueType, err error) {
552541
value, err = GetInt([]byte(test.json), test.path...)
553542
return value, Number, err
@@ -560,7 +549,7 @@ func TestGetInt(t *testing.T) {
560549
}
561550

562551
func TestGetFloat(t *testing.T) {
563-
runTests(t, getFloatTests,
552+
runGetTests(t, "GetFloat()", getFloatTests,
564553
func(test GetTest) (value interface{}, dataType ValueType, err error) {
565554
value, err = GetFloat([]byte(test.json), test.path...)
566555
return value, Number, err
@@ -573,7 +562,7 @@ func TestGetFloat(t *testing.T) {
573562
}
574563

575564
func TestGetBoolean(t *testing.T) {
576-
runTests(t, getBoolTests,
565+
runGetTests(t, "GetBoolean()", getBoolTests,
577566
func(test GetTest) (value interface{}, dataType ValueType, err error) {
578567
value, err = GetBoolean([]byte(test.json), test.path...)
579568
return value, Boolean, err
@@ -586,7 +575,7 @@ func TestGetBoolean(t *testing.T) {
586575
}
587576

588577
func TestGetSlice(t *testing.T) {
589-
runTests(t, getArrayTests,
578+
runGetTests(t, "Get()-for-arrays", getArrayTests,
590579
func(test GetTest) (value interface{}, dataType ValueType, err error) {
591580
value, dataType, _, err = Get([]byte(test.json), test.path...)
592581
return
@@ -627,3 +616,164 @@ func TestArrayEach(t *testing.T) {
627616
}
628617
}, "a", "b")
629618
}
619+
620+
type ParseTest struct {
621+
in string
622+
intype ValueType
623+
out interface{}
624+
isErr bool
625+
}
626+
627+
var parseBoolTests = []ParseTest{
628+
ParseTest{
629+
in: "true",
630+
intype: Boolean,
631+
out: true,
632+
},
633+
ParseTest{
634+
in: "false",
635+
intype: Boolean,
636+
out: false,
637+
},
638+
ParseTest{
639+
in: "foo",
640+
intype: Boolean,
641+
isErr: true,
642+
},
643+
ParseTest{
644+
in: "trux",
645+
intype: Boolean,
646+
isErr: true,
647+
},
648+
ParseTest{
649+
in: "truex",
650+
intype: Boolean,
651+
isErr: true,
652+
},
653+
ParseTest{
654+
in: "",
655+
intype: Boolean,
656+
isErr: true,
657+
},
658+
}
659+
660+
var parseFloatTest = []ParseTest{
661+
ParseTest{
662+
in: "0",
663+
intype: Number,
664+
out: float64(0),
665+
},
666+
ParseTest{
667+
in: "0.0",
668+
intype: Number,
669+
out: float64(0.0),
670+
},
671+
ParseTest{
672+
in: "1",
673+
intype: Number,
674+
out: float64(1),
675+
},
676+
ParseTest{
677+
in: "1.234",
678+
intype: Number,
679+
out: float64(1.234),
680+
},
681+
ParseTest{
682+
in: "1.234e5",
683+
intype: Number,
684+
out: float64(1.234e5),
685+
},
686+
ParseTest{
687+
in: "-1.234e5",
688+
intype: Number,
689+
out: float64(-1.234e5),
690+
},
691+
ParseTest{
692+
in: "+1.234e5", // Note: + sign not allowed under RFC7159, but our parser accepts it since it uses strconv.ParseFloat
693+
intype: Number,
694+
out: float64(1.234e5),
695+
},
696+
ParseTest{
697+
in: "1.2.3",
698+
intype: Number,
699+
isErr: true,
700+
},
701+
ParseTest{
702+
in: "1..1",
703+
intype: Number,
704+
isErr: true,
705+
},
706+
ParseTest{
707+
in: "1a",
708+
intype: Number,
709+
isErr: true,
710+
},
711+
ParseTest{
712+
in: "",
713+
intype: Number,
714+
isErr: true,
715+
},
716+
}
717+
718+
// parseTestCheckNoError checks the error return from Parse*() against the test case expectations.
719+
// Returns true the test should proceed to checking the actual data returned from Parse*(), or false if the test is finished.
720+
func parseTestCheckNoError(t *testing.T, testKind string, test ParseTest, value interface{}, err error) bool {
721+
if isErr := (err != nil); test.isErr != isErr {
722+
// If the call didn't match the error expectation, fail
723+
t.Errorf("%s test '%s' isErr mismatch: expected %t, obtained %t (err %v). Obtained value: %v", testKind, test.in, test.isErr, isErr, err, value)
724+
return false
725+
} else if isErr {
726+
// Else, if there was an error, don't fail and don't check isFound or the value
727+
return false
728+
} else {
729+
// Else, there was no error and a value was found, so check the value
730+
return true
731+
}
732+
}
733+
734+
func runParseTests(t *testing.T, testKind string, tests []ParseTest, runner func(ParseTest) (interface{}, error), resultChecker func(ParseTest, interface{}) (bool, interface{})) {
735+
for _, test := range tests {
736+
value, err := runner(test)
737+
738+
if parseTestCheckNoError(t, testKind, test, value, err) {
739+
if test.out == nil {
740+
t.Errorf("MALFORMED TEST: %v", test)
741+
continue
742+
}
743+
744+
if ok, expected := resultChecker(test, value); !ok {
745+
if expectedBytes, ok := expected.([]byte); ok {
746+
expected = string(expectedBytes)
747+
}
748+
if valueBytes, ok := value.([]byte); ok {
749+
value = string(valueBytes)
750+
}
751+
t.Errorf("%s test '%s' expected to return value %v, but did returned %v instead", testKind, test.in, expected, value)
752+
}
753+
}
754+
}
755+
}
756+
757+
func TestParseBoolean(t *testing.T) {
758+
runParseTests(t, "ParseBoolean()", parseBoolTests,
759+
func(test ParseTest) (value interface{}, err error) {
760+
return ParseBoolean([]byte(test.in))
761+
},
762+
func(test ParseTest, obtained interface{}) (bool, interface{}) {
763+
expected := test.out.(bool)
764+
return obtained.(bool) == expected, expected
765+
},
766+
)
767+
}
768+
769+
func TestParseFloat(t *testing.T) {
770+
runParseTests(t, "ParseFloat()", parseFloatTest,
771+
func(test ParseTest) (value interface{}, err error) {
772+
return ParseFloat([]byte(test.in))
773+
},
774+
func(test ParseTest, obtained interface{}) (bool, interface{}) {
775+
expected := test.out.(float64)
776+
return obtained.(float64) == expected, expected
777+
},
778+
)
779+
}

0 commit comments

Comments
 (0)