...

Source file src/github.com/jmespath/go-jmespath/lexer_test.go

Documentation: github.com/jmespath/go-jmespath

     1  package jmespath
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/jmespath/go-jmespath/internal/testify/assert"
     8  )
     9  
    10  var lexingTests = []struct {
    11  	expression string
    12  	expected   []token
    13  }{
    14  	{"*", []token{{tStar, "*", 0, 1}}},
    15  	{".", []token{{tDot, ".", 0, 1}}},
    16  	{"[?", []token{{tFilter, "[?", 0, 2}}},
    17  	{"[]", []token{{tFlatten, "[]", 0, 2}}},
    18  	{"(", []token{{tLparen, "(", 0, 1}}},
    19  	{")", []token{{tRparen, ")", 0, 1}}},
    20  	{"[", []token{{tLbracket, "[", 0, 1}}},
    21  	{"]", []token{{tRbracket, "]", 0, 1}}},
    22  	{"{", []token{{tLbrace, "{", 0, 1}}},
    23  	{"}", []token{{tRbrace, "}", 0, 1}}},
    24  	{"||", []token{{tOr, "||", 0, 2}}},
    25  	{"|", []token{{tPipe, "|", 0, 1}}},
    26  	{"29", []token{{tNumber, "29", 0, 2}}},
    27  	{"2", []token{{tNumber, "2", 0, 1}}},
    28  	{"0", []token{{tNumber, "0", 0, 1}}},
    29  	{"-20", []token{{tNumber, "-20", 0, 3}}},
    30  	{"foo", []token{{tUnquotedIdentifier, "foo", 0, 3}}},
    31  	{`"bar"`, []token{{tQuotedIdentifier, "bar", 0, 3}}},
    32  	// Escaping the delimiter
    33  	{`"bar\"baz"`, []token{{tQuotedIdentifier, `bar"baz`, 0, 7}}},
    34  	{",", []token{{tComma, ",", 0, 1}}},
    35  	{":", []token{{tColon, ":", 0, 1}}},
    36  	{"<", []token{{tLT, "<", 0, 1}}},
    37  	{"<=", []token{{tLTE, "<=", 0, 2}}},
    38  	{">", []token{{tGT, ">", 0, 1}}},
    39  	{">=", []token{{tGTE, ">=", 0, 2}}},
    40  	{"==", []token{{tEQ, "==", 0, 2}}},
    41  	{"!=", []token{{tNE, "!=", 0, 2}}},
    42  	{"`[0, 1, 2]`", []token{{tJSONLiteral, "[0, 1, 2]", 1, 9}}},
    43  	{"'foo'", []token{{tStringLiteral, "foo", 1, 3}}},
    44  	{"'a'", []token{{tStringLiteral, "a", 1, 1}}},
    45  	{`'foo\'bar'`, []token{{tStringLiteral, "foo'bar", 1, 7}}},
    46  	{"@", []token{{tCurrent, "@", 0, 1}}},
    47  	{"&", []token{{tExpref, "&", 0, 1}}},
    48  	// Quoted identifier unicode escape sequences
    49  	{`"\u2713"`, []token{{tQuotedIdentifier, "✓", 0, 3}}},
    50  	{`"\\"`, []token{{tQuotedIdentifier, `\`, 0, 1}}},
    51  	{"`\"foo\"`", []token{{tJSONLiteral, "\"foo\"", 1, 5}}},
    52  	// Combinations of tokens.
    53  	{"foo.bar", []token{
    54  		{tUnquotedIdentifier, "foo", 0, 3},
    55  		{tDot, ".", 3, 1},
    56  		{tUnquotedIdentifier, "bar", 4, 3},
    57  	}},
    58  	{"foo[0]", []token{
    59  		{tUnquotedIdentifier, "foo", 0, 3},
    60  		{tLbracket, "[", 3, 1},
    61  		{tNumber, "0", 4, 1},
    62  		{tRbracket, "]", 5, 1},
    63  	}},
    64  	{"foo[?a<b]", []token{
    65  		{tUnquotedIdentifier, "foo", 0, 3},
    66  		{tFilter, "[?", 3, 2},
    67  		{tUnquotedIdentifier, "a", 5, 1},
    68  		{tLT, "<", 6, 1},
    69  		{tUnquotedIdentifier, "b", 7, 1},
    70  		{tRbracket, "]", 8, 1},
    71  	}},
    72  }
    73  
    74  func TestCanLexTokens(t *testing.T) {
    75  	assert := assert.New(t)
    76  	lexer := NewLexer()
    77  	for _, tt := range lexingTests {
    78  		tokens, err := lexer.tokenize(tt.expression)
    79  		if assert.Nil(err) {
    80  			errMsg := fmt.Sprintf("Mismatch expected number of tokens: (expected: %s, actual: %s)",
    81  				tt.expected, tokens)
    82  			tt.expected = append(tt.expected, token{tEOF, "", len(tt.expression), 0})
    83  			if assert.Equal(len(tt.expected), len(tokens), errMsg) {
    84  				for i, token := range tokens {
    85  					expected := tt.expected[i]
    86  					assert.Equal(expected, token, "Token not equal")
    87  				}
    88  			}
    89  		}
    90  	}
    91  }
    92  
    93  var lexingErrorTests = []struct {
    94  	expression string
    95  	msg        string
    96  }{
    97  	{"'foo", "Missing closing single quote"},
    98  	{"[?foo==bar?]", "Unknown char '?'"},
    99  }
   100  
   101  func TestLexingErrors(t *testing.T) {
   102  	assert := assert.New(t)
   103  	lexer := NewLexer()
   104  	for _, tt := range lexingErrorTests {
   105  		_, err := lexer.tokenize(tt.expression)
   106  		assert.NotNil(err, fmt.Sprintf("Expected lexing error: %s", tt.msg))
   107  	}
   108  }
   109  
   110  var exprIdentifier = "abcdefghijklmnopqrstuvwxyz"
   111  var exprSubexpr = "abcdefghijklmnopqrstuvwxyz.abcdefghijklmnopqrstuvwxyz"
   112  var deeplyNested50 = "j49.j48.j47.j46.j45.j44.j43.j42.j41.j40.j39.j38.j37.j36.j35.j34.j33.j32.j31.j30.j29.j28.j27.j26.j25.j24.j23.j22.j21.j20.j19.j18.j17.j16.j15.j14.j13.j12.j11.j10.j9.j8.j7.j6.j5.j4.j3.j2.j1.j0"
   113  var deeplyNested50Pipe = "j49|j48|j47|j46|j45|j44|j43|j42|j41|j40|j39|j38|j37|j36|j35|j34|j33|j32|j31|j30|j29|j28|j27|j26|j25|j24|j23|j22|j21|j20|j19|j18|j17|j16|j15|j14|j13|j12|j11|j10|j9|j8|j7|j6|j5|j4|j3|j2|j1|j0"
   114  var deeplyNested50Index = "[49][48][47][46][45][44][43][42][41][40][39][38][37][36][35][34][33][32][31][30][29][28][27][26][25][24][23][22][21][20][19][18][17][16][15][14][13][12][11][10][9][8][7][6][5][4][3][2][1][0]"
   115  var deepProjection104 = "a[*].b[*].c[*].d[*].e[*].f[*].g[*].h[*].i[*].j[*].k[*].l[*].m[*].n[*].o[*].p[*].q[*].r[*].s[*].t[*].u[*].v[*].w[*].x[*].y[*].z[*].a[*].b[*].c[*].d[*].e[*].f[*].g[*].h[*].i[*].j[*].k[*].l[*].m[*].n[*].o[*].p[*].q[*].r[*].s[*].t[*].u[*].v[*].w[*].x[*].y[*].z[*].a[*].b[*].c[*].d[*].e[*].f[*].g[*].h[*].i[*].j[*].k[*].l[*].m[*].n[*].o[*].p[*].q[*].r[*].s[*].t[*].u[*].v[*].w[*].x[*].y[*].z[*].a[*].b[*].c[*].d[*].e[*].f[*].g[*].h[*].i[*].j[*].k[*].l[*].m[*].n[*].o[*].p[*].q[*].r[*].s[*].t[*].u[*].v[*].w[*].x[*].y[*].z[*]"
   116  var exprQuotedIdentifier = `"abcdefghijklmnopqrstuvwxyz.abcdefghijklmnopqrstuvwxyz"`
   117  var quotedIdentifierEscapes = `"\n\r\b\t\n\r\b\t\n\r\b\t\n\r\b\t\n\r\b\t\n\r\b\t\n\r\b\t"`
   118  var rawStringLiteral = `'abcdefghijklmnopqrstuvwxyz.abcdefghijklmnopqrstuvwxyz'`
   119  
   120  func BenchmarkLexIdentifier(b *testing.B) {
   121  	runLexBenchmark(b, exprIdentifier)
   122  }
   123  
   124  func BenchmarkLexSubexpression(b *testing.B) {
   125  	runLexBenchmark(b, exprSubexpr)
   126  }
   127  
   128  func BenchmarkLexDeeplyNested50(b *testing.B) {
   129  	runLexBenchmark(b, deeplyNested50)
   130  }
   131  
   132  func BenchmarkLexDeepNested50Pipe(b *testing.B) {
   133  	runLexBenchmark(b, deeplyNested50Pipe)
   134  }
   135  
   136  func BenchmarkLexDeepNested50Index(b *testing.B) {
   137  	runLexBenchmark(b, deeplyNested50Index)
   138  }
   139  
   140  func BenchmarkLexQuotedIdentifier(b *testing.B) {
   141  	runLexBenchmark(b, exprQuotedIdentifier)
   142  }
   143  
   144  func BenchmarkLexQuotedIdentifierEscapes(b *testing.B) {
   145  	runLexBenchmark(b, quotedIdentifierEscapes)
   146  }
   147  
   148  func BenchmarkLexRawStringLiteral(b *testing.B) {
   149  	runLexBenchmark(b, rawStringLiteral)
   150  }
   151  
   152  func BenchmarkLexDeepProjection104(b *testing.B) {
   153  	runLexBenchmark(b, deepProjection104)
   154  }
   155  
   156  func runLexBenchmark(b *testing.B, expression string) {
   157  	assert := assert.New(b)
   158  	lexer := NewLexer()
   159  	for i := 0; i < b.N; i++ {
   160  		_, err := lexer.tokenize(expression)
   161  		if err != nil {
   162  			assert.Fail("Could not lex expression")
   163  		}
   164  	}
   165  }
   166  

View as plain text