github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/logql/log/jsonexpr/jsonexpr_test.go (about)

     1  package jsonexpr
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/require"
     8  )
     9  
    10  func TestJSONExpressionParser(t *testing.T) {
    11  	// {"app":"foo","field with space":"value","field with ÜFT8👌":true,"namespace":"prod","pod":{"uuid":"foo","deployment":{"ref":"foobar", "params": [{"param": true},2,3]}}}
    12  
    13  	tests := []struct {
    14  		name       string
    15  		expression string
    16  		want       []interface{}
    17  		error      error
    18  	}{
    19  		{
    20  			"single field",
    21  			"app",
    22  			[]interface{}{"app"},
    23  			nil,
    24  		},
    25  		{
    26  			"top-level field with spaces",
    27  			`["field with space"]`,
    28  			[]interface{}{"field with space"},
    29  			nil,
    30  		},
    31  		{
    32  			"top-level field with UTF8",
    33  			`["field with ÜFT8👌"]`,
    34  			[]interface{}{"field with ÜFT8👌"},
    35  			nil,
    36  		},
    37  		{
    38  			"top-level array access",
    39  			`[0]`,
    40  			[]interface{}{0},
    41  			nil,
    42  		},
    43  		{
    44  			"nested field",
    45  			`pod.uuid`,
    46  			[]interface{}{"pod", "uuid"},
    47  			nil,
    48  		},
    49  		{
    50  			"nested field alternate syntax",
    51  			`pod["uuid"]`,
    52  			[]interface{}{"pod", "uuid"},
    53  			nil,
    54  		},
    55  		{
    56  			"nested field alternate syntax 2",
    57  			`["pod"]["uuid"]`,
    58  			[]interface{}{"pod", "uuid"},
    59  			nil,
    60  		},
    61  		{
    62  			"array access",
    63  			`pod.deployment.params[0]`,
    64  			[]interface{}{"pod", "deployment", "params", 0},
    65  			nil,
    66  		},
    67  		{
    68  			"multi-level array access",
    69  			`pod.deployment.params[0].param`,
    70  			[]interface{}{"pod", "deployment", "params", 0, "param"},
    71  			nil,
    72  		},
    73  		{
    74  			"multi-level array access alternate syntax",
    75  			`pod.deployment.params[0]["param"]`,
    76  			[]interface{}{"pod", "deployment", "params", 0, "param"},
    77  			nil,
    78  		},
    79  		{
    80  			"empty",
    81  			``,
    82  			nil,
    83  			nil,
    84  		},
    85  
    86  		{
    87  			"invalid field access",
    88  			`field with space`,
    89  			nil,
    90  			fmt.Errorf("syntax error: unexpected FIELD"),
    91  		},
    92  		{
    93  			"missing opening square bracket",
    94  			`"pod"]`,
    95  			nil,
    96  			fmt.Errorf("syntax error: unexpected STRING, expecting LSB or FIELD"),
    97  		},
    98  		{
    99  			"missing closing square bracket",
   100  			`["pod"`,
   101  			nil,
   102  			fmt.Errorf("syntax error: unexpected $end, expecting RSB"),
   103  		},
   104  		{
   105  			"missing closing square bracket",
   106  			`["pod""deployment"]`,
   107  			nil,
   108  			fmt.Errorf("syntax error: unexpected STRING, expecting RSB"),
   109  		},
   110  		{
   111  			"invalid nesting",
   112  			`pod..uuid`,
   113  			nil,
   114  			fmt.Errorf("syntax error: unexpected DOT, expecting FIELD"),
   115  		},
   116  		{
   117  			"syntax error on key access",
   118  			`["key`,
   119  			nil,
   120  			fmt.Errorf("syntax error: unexpected $end, expecting RSB"),
   121  		},
   122  		{
   123  			"identifier with number",
   124  			`utf8`,
   125  			[]interface{}{"utf8"},
   126  			nil,
   127  		},
   128  	}
   129  	for _, tt := range tests {
   130  		t.Run(tt.name, func(t *testing.T) {
   131  			parsed, err := Parse(tt.expression, false)
   132  
   133  			require.Equal(t, tt.want, parsed)
   134  
   135  			if tt.error == nil {
   136  				return
   137  			}
   138  
   139  			require.NotNil(t, err)
   140  			require.Equal(t, tt.error.Error(), err.Error())
   141  		})
   142  	}
   143  }