1package jmespath
2
3import (
4	"encoding/json"
5	"fmt"
6	"io/ioutil"
7	"os"
8	"path/filepath"
9	"testing"
10
11	"github.com/stretchr/testify/assert"
12)
13
14type TestSuite struct {
15	Given     interface{}
16	TestCases []TestCase `json:"cases"`
17	Comment   string
18}
19type TestCase struct {
20	Comment    string
21	Expression string
22	Result     interface{}
23	Error      string
24}
25
26var whiteListed = []string{
27	"compliance/basic.json",
28	"compliance/current.json",
29	"compliance/escape.json",
30	"compliance/filters.json",
31	"compliance/functions.json",
32	"compliance/identifiers.json",
33	"compliance/indices.json",
34	"compliance/literal.json",
35	"compliance/multiselect.json",
36	"compliance/ormatch.json",
37	"compliance/pipe.json",
38	"compliance/slice.json",
39	"compliance/syntax.json",
40	"compliance/unicode.json",
41	"compliance/wildcard.json",
42	"compliance/boolean.json",
43}
44
45func allowed(path string) bool {
46	for _, el := range whiteListed {
47		if el == path {
48			return true
49		}
50	}
51	return false
52}
53
54func TestCompliance(t *testing.T) {
55	assert := assert.New(t)
56
57	var complianceFiles []string
58	err := filepath.Walk("compliance", func(path string, _ os.FileInfo, _ error) error {
59		//if strings.HasSuffix(path, ".json") {
60		if allowed(path) {
61			complianceFiles = append(complianceFiles, path)
62		}
63		return nil
64	})
65	if assert.Nil(err) {
66		for _, filename := range complianceFiles {
67			runComplianceTest(assert, filename)
68		}
69	}
70}
71
72func runComplianceTest(assert *assert.Assertions, filename string) {
73	var testSuites []TestSuite
74	data, err := ioutil.ReadFile(filename)
75	if assert.Nil(err) {
76		err := json.Unmarshal(data, &testSuites)
77		if assert.Nil(err) {
78			for _, testsuite := range testSuites {
79				runTestSuite(assert, testsuite, filename)
80			}
81		}
82	}
83}
84
85func runTestSuite(assert *assert.Assertions, testsuite TestSuite, filename string) {
86	for _, testcase := range testsuite.TestCases {
87		if testcase.Error != "" {
88			// This is a test case that verifies we error out properly.
89			runSyntaxTestCase(assert, testsuite.Given, testcase, filename)
90		} else {
91			runTestCase(assert, testsuite.Given, testcase, filename)
92		}
93	}
94}
95
96func runSyntaxTestCase(assert *assert.Assertions, given interface{}, testcase TestCase, filename string) {
97	// Anything with an .Error means that we expect that JMESPath should return
98	// an error when we try to evaluate the expression.
99	_, err := Search(testcase.Expression, given)
100	assert.NotNil(err, fmt.Sprintf("Expression: %s", testcase.Expression))
101}
102
103func runTestCase(assert *assert.Assertions, given interface{}, testcase TestCase, filename string) {
104	lexer := NewLexer()
105	var err error
106	_, err = lexer.tokenize(testcase.Expression)
107	if err != nil {
108		errMsg := fmt.Sprintf("(%s) Could not lex expression: %s -- %s", filename, testcase.Expression, err.Error())
109		assert.Fail(errMsg)
110		return
111	}
112	parser := NewParser()
113	_, err = parser.Parse(testcase.Expression)
114	if err != nil {
115		errMsg := fmt.Sprintf("(%s) Could not parse expression: %s -- %s", filename, testcase.Expression, err.Error())
116		assert.Fail(errMsg)
117		return
118	}
119	actual, err := Search(testcase.Expression, given)
120	if assert.Nil(err, fmt.Sprintf("Expression: %s", testcase.Expression)) {
121		assert.Equal(testcase.Result, actual, fmt.Sprintf("Expression: %s", testcase.Expression))
122	}
123}
124