github.com/netdata/go.d.plugin@v0.58.1/pkg/logs/json_test.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package logs
     4  
     5  import (
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  func TestNewJSONParser(t *testing.T) {
    14  	tests := map[string]struct {
    15  		config  JSONConfig
    16  		wantErr bool
    17  	}{
    18  		"empty config": {
    19  			config:  JSONConfig{},
    20  			wantErr: false,
    21  		},
    22  		"with mappings": {
    23  			config:  JSONConfig{Mapping: map[string]string{"from_field_1": "to_field_1"}},
    24  			wantErr: false,
    25  		},
    26  	}
    27  
    28  	for name, test := range tests {
    29  		t.Run(name, func(t *testing.T) {
    30  			p, err := NewJSONParser(test.config, nil)
    31  
    32  			if test.wantErr {
    33  				assert.Error(t, err)
    34  				assert.Nil(t, p)
    35  			} else {
    36  				assert.NoError(t, err)
    37  				assert.NotNil(t, p)
    38  			}
    39  		})
    40  	}
    41  }
    42  
    43  func TestJSONParser_ReadLine(t *testing.T) {
    44  	tests := map[string]struct {
    45  		config       JSONConfig
    46  		input        string
    47  		wantAssigned map[string]string
    48  		wantErr      bool
    49  	}{
    50  		"string value": {
    51  			input:   `{ "string": "example.com" }`,
    52  			wantErr: false,
    53  			wantAssigned: map[string]string{
    54  				"string": "example.com",
    55  			},
    56  		},
    57  		"int value": {
    58  			input:   `{ "int": 1 }`,
    59  			wantErr: false,
    60  			wantAssigned: map[string]string{
    61  				"int": "1",
    62  			},
    63  		},
    64  		"float value": {
    65  			input:   `{ "float": 1.1 }`,
    66  			wantErr: false,
    67  			wantAssigned: map[string]string{
    68  				"float": "1.1",
    69  			},
    70  		},
    71  		"string, int, float values": {
    72  			input:   `{ "string": "example.com", "int": 1, "float": 1.1 }`,
    73  			wantErr: false,
    74  			wantAssigned: map[string]string{
    75  				"string": "example.com",
    76  				"int":    "1",
    77  				"float":  "1.1",
    78  			},
    79  		},
    80  		"string, int, float values with mappings": {
    81  			config: JSONConfig{Mapping: map[string]string{
    82  				"string": "STRING",
    83  				"int":    "INT",
    84  				"float":  "FLOAT",
    85  			}},
    86  			input:   `{ "string": "example.com", "int": 1, "float": 1.1 }`,
    87  			wantErr: false,
    88  			wantAssigned: map[string]string{
    89  				"STRING": "example.com",
    90  				"INT":    "1",
    91  				"FLOAT":  "1.1",
    92  			},
    93  		},
    94  		"nested": {
    95  			input: `{"one":{"two":2,"three":{"four":4}},"five":5}`,
    96  			config: JSONConfig{Mapping: map[string]string{
    97  				"one.two": "mapped_value",
    98  			}},
    99  			wantErr: false,
   100  			wantAssigned: map[string]string{
   101  				"mapped_value":   "2",
   102  				"one.three.four": "4",
   103  				"five":           "5",
   104  			},
   105  		},
   106  		"nested with array": {
   107  			input: `{"one":{"two":[2,22]},"five":5}`,
   108  			config: JSONConfig{Mapping: map[string]string{
   109  				"one.two.1": "mapped_value",
   110  			}},
   111  			wantErr: false,
   112  			wantAssigned: map[string]string{
   113  				"one.two.0":    "2",
   114  				"mapped_value": "22",
   115  				"five":         "5",
   116  			},
   117  		},
   118  		"error on malformed JSON": {
   119  			input:   `{ "host"": unquoted_string}`,
   120  			wantErr: true,
   121  		},
   122  		"error on empty input": {
   123  			wantErr: true,
   124  		},
   125  	}
   126  
   127  	for name, test := range tests {
   128  		t.Run(name, func(t *testing.T) {
   129  			line := newLogLine()
   130  			in := strings.NewReader(test.input)
   131  			p, err := NewJSONParser(test.config, in)
   132  			require.NoError(t, err)
   133  			require.NotNil(t, p)
   134  
   135  			err = p.ReadLine(line)
   136  
   137  			if test.wantErr {
   138  				assert.Error(t, err)
   139  			} else {
   140  				require.NoError(t, err)
   141  				assert.Equal(t, test.wantAssigned, line.assigned)
   142  			}
   143  		})
   144  	}
   145  }
   146  
   147  func TestJSONParser_Parse(t *testing.T) {
   148  	tests := map[string]struct {
   149  		config       JSONConfig
   150  		input        string
   151  		wantAssigned map[string]string
   152  		wantErr      bool
   153  	}{
   154  		"string value": {
   155  			input:   `{ "string": "example.com" }`,
   156  			wantErr: false,
   157  			wantAssigned: map[string]string{
   158  				"string": "example.com",
   159  			},
   160  		},
   161  		"int value": {
   162  			input:   `{ "int": 1 }`,
   163  			wantErr: false,
   164  			wantAssigned: map[string]string{
   165  				"int": "1",
   166  			},
   167  		},
   168  		"float value": {
   169  			input:   `{ "float": 1.1 }`,
   170  			wantErr: false,
   171  			wantAssigned: map[string]string{
   172  				"float": "1.1",
   173  			},
   174  		},
   175  		"string, int, float values": {
   176  			input:   `{ "string": "example.com", "int": 1, "float": 1.1 }`,
   177  			wantErr: false,
   178  			wantAssigned: map[string]string{
   179  				"string": "example.com",
   180  				"int":    "1",
   181  				"float":  "1.1",
   182  			},
   183  		},
   184  		"string, int, float values with mappings": {
   185  			config: JSONConfig{Mapping: map[string]string{
   186  				"string": "STRING",
   187  				"int":    "INT",
   188  				"float":  "FLOAT",
   189  			}},
   190  			input:   `{ "string": "example.com", "int": 1, "float": 1.1 }`,
   191  			wantErr: false,
   192  			wantAssigned: map[string]string{
   193  				"STRING": "example.com",
   194  				"INT":    "1",
   195  				"FLOAT":  "1.1",
   196  			},
   197  		},
   198  		"error on malformed JSON": {
   199  			input:   `{ "host"": unquoted_string}`,
   200  			wantErr: true,
   201  		},
   202  		"error on empty input": {
   203  			wantErr: true,
   204  		},
   205  	}
   206  
   207  	for name, test := range tests {
   208  		t.Run(name, func(t *testing.T) {
   209  			line := newLogLine()
   210  			p, err := NewJSONParser(test.config, nil)
   211  			require.NoError(t, err)
   212  			require.NotNil(t, p)
   213  
   214  			err = p.Parse([]byte(test.input), line)
   215  
   216  			if test.wantErr {
   217  				assert.Error(t, err)
   218  			} else {
   219  				require.NoError(t, err)
   220  				assert.Equal(t, test.wantAssigned, line.assigned)
   221  			}
   222  		})
   223  	}
   224  }