github.com/observiq/carbon@v0.9.11-0.20200820160507-1b872e368a5e/operator/builtin/parser/json_test.go (about) 1 package parser 2 3 import ( 4 "context" 5 "testing" 6 "time" 7 8 jsoniter "github.com/json-iterator/go" 9 "github.com/observiq/carbon/entry" 10 "github.com/observiq/carbon/operator" 11 "github.com/observiq/carbon/operator/helper" 12 "github.com/observiq/carbon/testutil" 13 14 "github.com/stretchr/testify/mock" 15 "github.com/stretchr/testify/require" 16 "go.uber.org/zap" 17 ) 18 19 func NewFakeJSONOperator() (*JSONParser, *testutil.Operator) { 20 mock := testutil.Operator{} 21 logger, _ := zap.NewProduction() 22 return &JSONParser{ 23 ParserOperator: helper.ParserOperator{ 24 TransformerOperator: helper.TransformerOperator{ 25 WriterOperator: helper.WriterOperator{ 26 BasicOperator: helper.BasicOperator{ 27 OperatorID: "test", 28 OperatorType: "json_parser", 29 SugaredLogger: logger.Sugar(), 30 }, 31 OutputOperators: []operator.Operator{&mock}, 32 }, 33 }, 34 ParseFrom: entry.NewRecordField("testfield"), 35 ParseTo: entry.NewRecordField("testparsed"), 36 }, 37 json: jsoniter.ConfigFastest, 38 }, &mock 39 } 40 41 func TestJSONImplementations(t *testing.T) { 42 require.Implements(t, (*operator.Operator)(nil), new(JSONParser)) 43 } 44 45 func TestJSONParser(t *testing.T) { 46 cases := []struct { 47 name string 48 inputRecord map[string]interface{} 49 expectedRecord map[string]interface{} 50 errorExpected bool 51 }{ 52 { 53 "simple", 54 map[string]interface{}{ 55 "testfield": `{}`, 56 }, 57 map[string]interface{}{ 58 "testparsed": map[string]interface{}{}, 59 }, 60 false, 61 }, 62 { 63 "nested", 64 map[string]interface{}{ 65 "testfield": `{"superkey":"superval"}`, 66 }, 67 map[string]interface{}{ 68 "testparsed": map[string]interface{}{ 69 "superkey": "superval", 70 }, 71 }, 72 false, 73 }, 74 } 75 76 for _, tc := range cases { 77 t.Run(tc.name, func(t *testing.T) { 78 input := entry.New() 79 input.Record = tc.inputRecord 80 81 output := entry.New() 82 output.Record = tc.expectedRecord 83 84 parser, mockOutput := NewFakeJSONOperator() 85 mockOutput.On("Process", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { 86 e := args[1].(*entry.Entry) 87 require.Equal(t, tc.expectedRecord, e.Record) 88 }).Return(nil) 89 90 err := parser.Process(context.Background(), input) 91 require.NoError(t, err) 92 }) 93 } 94 } 95 96 func TestJSONParserWithEmbeddedTimeParser(t *testing.T) { 97 98 testTime := time.Unix(1136214245, 0) 99 100 cases := []struct { 101 name string 102 inputRecord map[string]interface{} 103 expectedRecord map[string]interface{} 104 errorExpected bool 105 preserve bool 106 }{ 107 { 108 "simple", 109 map[string]interface{}{ 110 "testfield": `{"timestamp":1136214245}`, 111 }, 112 map[string]interface{}{ 113 "testparsed": map[string]interface{}{}, 114 }, 115 false, 116 false, 117 }, 118 { 119 "preserve", 120 map[string]interface{}{ 121 "testfield": `{"timestamp":"1136214245"}`, 122 }, 123 map[string]interface{}{ 124 "testparsed": map[string]interface{}{ 125 "timestamp": "1136214245", 126 }, 127 }, 128 false, 129 true, 130 }, 131 { 132 "nested", 133 map[string]interface{}{ 134 "testfield": `{"superkey":"superval","timestamp":1136214245.123}`, 135 }, 136 map[string]interface{}{ 137 "testparsed": map[string]interface{}{ 138 "superkey": "superval", 139 }, 140 }, 141 false, 142 false, 143 }, 144 } 145 146 for _, tc := range cases { 147 t.Run(tc.name, func(t *testing.T) { 148 input := entry.New() 149 input.Record = tc.inputRecord 150 151 output := entry.New() 152 output.Record = tc.expectedRecord 153 154 parser, mockOutput := NewFakeJSONOperator() 155 parseFrom := entry.NewRecordField("testparsed", "timestamp") 156 parser.ParserOperator.TimeParser = &helper.TimeParser{ 157 ParseFrom: &parseFrom, 158 LayoutType: "epoch", 159 Layout: "s", 160 Preserve: tc.preserve, 161 } 162 mockOutput.On("Process", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { 163 e := args[1].(*entry.Entry) 164 require.Equal(t, tc.expectedRecord, e.Record) 165 require.Equal(t, testTime, e.Timestamp) 166 }).Return(nil) 167 168 err := parser.Process(context.Background(), input) 169 require.NoError(t, err) 170 }) 171 } 172 }