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  }