github.com/Jeffail/benthos/v3@v3.65.0/lib/processor/process_field_test.go (about)

     1  package processor
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  
     7  	"github.com/Jeffail/benthos/v3/lib/condition"
     8  	"github.com/Jeffail/benthos/v3/lib/log"
     9  	"github.com/Jeffail/benthos/v3/lib/message"
    10  	"github.com/Jeffail/benthos/v3/lib/metrics"
    11  )
    12  
    13  func TestProcessFieldParts(t *testing.T) {
    14  	conf := NewConfig()
    15  	conf.Type = "process_field"
    16  	conf.ProcessField.Path = "foo.bar"
    17  	conf.ProcessField.Parts = []int{1}
    18  
    19  	procConf := NewConfig()
    20  	procConf.Type = "json"
    21  	procConf.JSON.Operator = "select"
    22  	procConf.JSON.Path = "baz"
    23  
    24  	conf.ProcessField.Processors = append(conf.ProcessField.Processors, procConf)
    25  
    26  	c, err := New(conf, nil, log.Noop(), metrics.Noop())
    27  	if err != nil {
    28  		t.Error(err)
    29  		return
    30  	}
    31  
    32  	exp := [][]byte{
    33  		[]byte(`{"foo":{"bar":{"baz":"original"}}}`),
    34  		[]byte(`{"foo":{"bar":"put me at the root"}}`),
    35  		[]byte(`{"foo":{"bar":{"baz":"original"}}}`),
    36  	}
    37  
    38  	msg, res := c.ProcessMessage(message.New([][]byte{
    39  		[]byte(`{"foo":{"bar":{"baz":"original"}}}`),
    40  		[]byte(`{"foo":{"bar":{"baz":"put me at the root"}}}`),
    41  		[]byte(`{"foo":{"bar":{"baz":"original"}}}`),
    42  	}))
    43  	if res != nil {
    44  		t.Error(res.Error())
    45  	}
    46  	if act := message.GetAllBytes(msg[0]); !reflect.DeepEqual(act, exp) {
    47  		t.Errorf("Wrong result: %s != %s", act, exp)
    48  	}
    49  }
    50  
    51  func TestProcessFieldAllParts(t *testing.T) {
    52  	conf := NewConfig()
    53  	conf.Type = "process_field"
    54  	conf.ProcessField.Path = "foo.bar"
    55  	conf.ProcessField.Parts = []int{}
    56  
    57  	procConf := NewConfig()
    58  	procConf.Type = "json"
    59  	procConf.JSON.Operator = "select"
    60  	procConf.JSON.Path = "baz"
    61  
    62  	conf.ProcessField.Processors = append(conf.ProcessField.Processors, procConf)
    63  
    64  	c, err := New(conf, nil, log.Noop(), metrics.Noop())
    65  	if err != nil {
    66  		t.Error(err)
    67  		return
    68  	}
    69  
    70  	exp := [][]byte{
    71  		[]byte(`{"foo":{"bar":"put me at the root"}}`),
    72  		[]byte(`{"foo":{"bar":"put me at the root"}}`),
    73  	}
    74  
    75  	msg, res := c.ProcessMessage(message.New([][]byte{
    76  		[]byte(`{"foo":{"bar":{"baz":"put me at the root"}}}`),
    77  		[]byte(`{"foo":{"bar":{"baz":"put me at the root"}}}`),
    78  	}))
    79  	if res != nil {
    80  		t.Error(res.Error())
    81  	}
    82  	if act := message.GetAllBytes(msg[0]); !reflect.DeepEqual(act, exp) {
    83  		t.Errorf("Wrong result: %s != %s", act, exp)
    84  	}
    85  }
    86  
    87  func TestProcessFieldBadCodec(t *testing.T) {
    88  	conf := NewConfig()
    89  	conf.Type = "process_field"
    90  	conf.ProcessField.Path = "foo.bar"
    91  	conf.ProcessField.Parts = []int{}
    92  
    93  	procConf := NewConfig()
    94  	procConf.Type = "json"
    95  	procConf.JSON.Operator = "select"
    96  	procConf.JSON.Path = "baz"
    97  
    98  	conf.ProcessField.Processors = append(conf.ProcessField.Processors, procConf)
    99  
   100  	c, err := New(conf, nil, log.Noop(), metrics.Noop())
   101  	if err != nil {
   102  		t.Error(err)
   103  		return
   104  	}
   105  
   106  	exp := [][]byte{
   107  		[]byte(`bar didnt exist`),
   108  		[]byte(`{"foo":{"bar":"put me at the root"}}`),
   109  	}
   110  
   111  	msg, res := c.ProcessMessage(message.New([][]byte{
   112  		[]byte(`bar didnt exist`),
   113  		[]byte(`{"foo":{"bar":{"baz":"put me at the root"}}}`),
   114  	}))
   115  	if res != nil {
   116  		t.Error(res.Error())
   117  	}
   118  	if act := message.GetAllBytes(msg[0]); !reflect.DeepEqual(act, exp) {
   119  		t.Errorf("Wrong result: %s != %s", act, exp)
   120  	}
   121  	if !HasFailed(msg[0].Get(0)) {
   122  		t.Error("Expected failed flag on part 0")
   123  	}
   124  	if HasFailed(msg[0].Get(1)) {
   125  		t.Error("Unexpected failed flag on part 1")
   126  	}
   127  }
   128  
   129  func TestProcessFieldMetadata(t *testing.T) {
   130  	conf := NewConfig()
   131  	conf.Type = "process_field"
   132  	conf.ProcessField.Codec = "metadata"
   133  	conf.ProcessField.Path = "foo"
   134  	conf.ProcessField.Parts = []int{}
   135  
   136  	procConf := NewConfig()
   137  	procConf.Type = TypeText
   138  	procConf.Text.Operator = "to_upper"
   139  
   140  	conf.ProcessField.Processors = append(conf.ProcessField.Processors, procConf)
   141  
   142  	c, err := New(conf, nil, log.Noop(), metrics.Noop())
   143  	if err != nil {
   144  		t.Fatal(err)
   145  	}
   146  
   147  	expParts := [][]byte{
   148  		[]byte(`this stays unchanged`),
   149  		[]byte(`this also stays unchanged`),
   150  	}
   151  
   152  	inputMsg := message.New(expParts)
   153  	inputMsg.Get(0).Metadata().Set("foo", "uppercase me").Set("bar", "leave me alone")
   154  	inputMsg.Get(1).Metadata().Set("foo", "uppercase me as well").Set("bar", "leave me alone as well")
   155  
   156  	msg, res := c.ProcessMessage(inputMsg)
   157  	if res != nil {
   158  		t.Error(res.Error())
   159  	}
   160  	if act := message.GetAllBytes(msg[0]); !reflect.DeepEqual(act, expParts) {
   161  		t.Errorf("Wrong result: %s != %s", act, expParts)
   162  	}
   163  	if exp, act := "UPPERCASE ME", msg[0].Get(0).Metadata().Get("foo"); exp != act {
   164  		t.Errorf("Wrong result: %v != %v", act, exp)
   165  	}
   166  	if exp, act := "leave me alone", msg[0].Get(0).Metadata().Get("bar"); exp != act {
   167  		t.Errorf("Wrong result: %v != %v", act, exp)
   168  	}
   169  	if exp, act := "UPPERCASE ME AS WELL", msg[0].Get(1).Metadata().Get("foo"); exp != act {
   170  		t.Errorf("Wrong result: %v != %v", act, exp)
   171  	}
   172  	if exp, act := "leave me alone as well", msg[0].Get(1).Metadata().Get("bar"); exp != act {
   173  		t.Errorf("Wrong result: %v != %v", act, exp)
   174  	}
   175  }
   176  
   177  func TestProcessFieldString(t *testing.T) {
   178  	conf := NewConfig()
   179  	conf.Type = "process_field"
   180  	conf.ProcessField.Path = "foo.bar"
   181  	conf.ProcessField.Parts = []int{}
   182  
   183  	procConf := NewConfig()
   184  	procConf.Type = "encode"
   185  
   186  	conf.ProcessField.Processors = append(conf.ProcessField.Processors, procConf)
   187  
   188  	c, err := New(conf, nil, log.Noop(), metrics.Noop())
   189  	if err != nil {
   190  		t.Error(err)
   191  		return
   192  	}
   193  
   194  	exp := [][]byte{
   195  		[]byte(`{"foo":{"bar":"ZW5jb2RlIG1l"}}`),
   196  		[]byte(`{"foo":{"bar":"ZW5jb2RlIG1lIHRvbw=="}}`),
   197  	}
   198  
   199  	msg, res := c.ProcessMessage(message.New([][]byte{
   200  		[]byte(`{"foo":{"bar":"encode me"}}`),
   201  		[]byte(`{"foo":{"bar":"encode me too"}}`),
   202  	}))
   203  	if res != nil {
   204  		t.Error(res.Error())
   205  	}
   206  	if act := message.GetAllBytes(msg[0]); !reflect.DeepEqual(act, exp) {
   207  		t.Errorf("Wrong result: %s != %s", act, exp)
   208  	}
   209  }
   210  
   211  func TestProcessFieldDiscard(t *testing.T) {
   212  	conf := NewConfig()
   213  	conf.Type = "process_field"
   214  	conf.ProcessField.Path = "foo.bar"
   215  	conf.ProcessField.Parts = []int{}
   216  	conf.ProcessField.ResultType = "discard"
   217  
   218  	procConf := NewConfig()
   219  	procConf.Type = "encode"
   220  
   221  	conf.ProcessField.Processors = append(conf.ProcessField.Processors, procConf)
   222  
   223  	c, err := New(conf, nil, log.Noop(), metrics.Noop())
   224  	if err != nil {
   225  		t.Error(err)
   226  		return
   227  	}
   228  
   229  	exp := [][]byte{
   230  		[]byte(`{"foo":{"bar":"encode me"}}`),
   231  		[]byte(`{"foo":{"bar":"encode me too"}}`),
   232  	}
   233  
   234  	msg, res := c.ProcessMessage(message.New([][]byte{
   235  		[]byte(`{"foo":{"bar":"encode me"}}`),
   236  		[]byte(`{"foo":{"bar":"encode me too"}}`),
   237  	}))
   238  	if res != nil {
   239  		t.Error(res.Error())
   240  	}
   241  	if act := message.GetAllBytes(msg[0]); !reflect.DeepEqual(act, exp) {
   242  		t.Errorf("Wrong result: %s != %s", act, exp)
   243  	}
   244  }
   245  
   246  func TestProcessFieldDiscardWithMetadata(t *testing.T) {
   247  	conf := NewConfig()
   248  	conf.Type = "process_field"
   249  	conf.ProcessField.Path = "foo.bar"
   250  	conf.ProcessField.Parts = []int{}
   251  	conf.ProcessField.ResultType = "discard"
   252  
   253  	procConf := NewConfig()
   254  	procConf.Type = TypeMetadata
   255  	procConf.Metadata.Operator = "set"
   256  	procConf.Metadata.Key = "foo"
   257  	procConf.Metadata.Value = "${!content()}"
   258  	conf.ProcessField.Processors = append(conf.ProcessField.Processors, procConf)
   259  
   260  	procConf = NewConfig()
   261  	procConf.Type = TypeEncode
   262  	conf.ProcessField.Processors = append(conf.ProcessField.Processors, procConf)
   263  
   264  	c, err := New(conf, nil, log.Noop(), metrics.Noop())
   265  	if err != nil {
   266  		t.Fatal(err)
   267  	}
   268  
   269  	exp := [][]byte{
   270  		[]byte(`{"foo":{"bar":"encode me"}}`),
   271  		[]byte(`{"foo":{"bar":"encode me too"}}`),
   272  	}
   273  
   274  	msg, res := c.ProcessMessage(message.New([][]byte{
   275  		[]byte(`{"foo":{"bar":"encode me"}}`),
   276  		[]byte(`{"foo":{"bar":"encode me too"}}`),
   277  	}))
   278  	if res != nil {
   279  		t.Error(res.Error())
   280  	}
   281  	if act := message.GetAllBytes(msg[0]); !reflect.DeepEqual(act, exp) {
   282  		t.Errorf("Wrong result: %s != %s", act, exp)
   283  	}
   284  	if exp, act := "encode me", msg[0].Get(0).Metadata().Get("foo"); exp != act {
   285  		t.Errorf("Unexpected metadata value: %v != %v", act, exp)
   286  	}
   287  	if exp, act := "encode me too", msg[0].Get(1).Metadata().Get("foo"); exp != act {
   288  		t.Errorf("Unexpected metadata value: %v != %v", act, exp)
   289  	}
   290  }
   291  
   292  func TestProcessFieldDiscardMisaligned(t *testing.T) {
   293  	conf := NewConfig()
   294  	conf.Type = "process_field"
   295  	conf.ProcessField.Path = "foo.bar"
   296  	conf.ProcessField.Parts = []int{}
   297  	conf.ProcessField.ResultType = "discard"
   298  
   299  	procConf := NewConfig()
   300  	procConf.Type = TypeMetadata
   301  	procConf.Metadata.Operator = "set"
   302  	procConf.Metadata.Key = "foo"
   303  	procConf.Metadata.Value = "${!content()}"
   304  	conf.ProcessField.Processors = append(conf.ProcessField.Processors, procConf)
   305  
   306  	procConf = NewConfig()
   307  	procConf.Type = TypeFilterParts
   308  	procConf.FilterParts.Type = condition.TypeText
   309  	procConf.FilterParts.Text.Operator = "equals"
   310  	procConf.FilterParts.Text.Arg = "encode me"
   311  	conf.ProcessField.Processors = append(conf.ProcessField.Processors, procConf)
   312  
   313  	c, err := New(conf, nil, log.Noop(), metrics.Noop())
   314  	if err != nil {
   315  		t.Fatal(err)
   316  	}
   317  
   318  	exp := [][]byte{
   319  		[]byte(`{"foo":{"bar":"encode me"}}`),
   320  		[]byte(`{"foo":{"bar":"encode me too"}}`),
   321  	}
   322  
   323  	msg, res := c.ProcessMessage(message.New([][]byte{
   324  		[]byte(`{"foo":{"bar":"encode me"}}`),
   325  		[]byte(`{"foo":{"bar":"encode me too"}}`),
   326  	}))
   327  	if res != nil {
   328  		t.Error(res.Error())
   329  	}
   330  	if act := message.GetAllBytes(msg[0]); !reflect.DeepEqual(act, exp) {
   331  		t.Errorf("Wrong result: %s != %s", act, exp)
   332  	}
   333  	if exp, act := "", msg[0].Get(0).Metadata().Get("foo"); exp != act {
   334  		t.Errorf("Unexpected metadata value: %v != %v", act, exp)
   335  	}
   336  	if exp, act := "", msg[0].Get(1).Metadata().Get("foo"); exp != act {
   337  		t.Errorf("Unexpected metadata value: %v != %v", act, exp)
   338  	}
   339  }
   340  
   341  func TestProcessFieldCodecs(t *testing.T) {
   342  	type testCase struct {
   343  		name   string
   344  		codec  string
   345  		input  string
   346  		output string
   347  	}
   348  	tests := []testCase{
   349  		{
   350  			name:   "string 1",
   351  			codec:  "string",
   352  			input:  `{"target":"foobar"}`,
   353  			output: `{"target":"foobar"}`,
   354  		},
   355  		{
   356  			name:   "int 1",
   357  			codec:  "int",
   358  			input:  `{"target":"5"}`,
   359  			output: `{"target":5}`,
   360  		},
   361  		{
   362  			name:   "float 1",
   363  			codec:  "float",
   364  			input:  `{"target":"5.67"}`,
   365  			output: `{"target":5.67}`,
   366  		},
   367  		{
   368  			name:   "bool 1",
   369  			codec:  "bool",
   370  			input:  `{"target":"true"}`,
   371  			output: `{"target":true}`,
   372  		},
   373  		{
   374  			name:   "bool 2",
   375  			codec:  "bool",
   376  			input:  `{"target":"false"}`,
   377  			output: `{"target":false}`,
   378  		},
   379  		{
   380  			name:   "object 1",
   381  			codec:  "object",
   382  			input:  `{"target":"{}"}`,
   383  			output: `{"target":{}}`,
   384  		},
   385  		{
   386  			name:   "object 2",
   387  			codec:  "object",
   388  			input:  `{"target":"{\"foo\":{\"bar\":\"baz\"}}"}`,
   389  			output: `{"target":{"foo":{"bar":"baz"}}}`,
   390  		},
   391  		{
   392  			name:   "object 2",
   393  			codec:  "object",
   394  			input:  `{"target":"null"}`,
   395  			output: `{"target":null}`,
   396  		},
   397  		{
   398  			name:   "array 1",
   399  			codec:  "array",
   400  			input:  `{"target":"[]"}`,
   401  			output: `{"target":[]}`,
   402  		},
   403  		{
   404  			name:   "array 2",
   405  			codec:  "array",
   406  			input:  `{"target":"[1,2,\"foo\"]"}`,
   407  			output: `{"target":[1,2,"foo"]}`,
   408  		},
   409  	}
   410  
   411  	procConf := NewConfig()
   412  	procConf.Type = "noop"
   413  
   414  	for _, test := range tests {
   415  		t.Run(test.name, func(tt *testing.T) {
   416  			conf := NewConfig()
   417  			conf.Type = "process_field"
   418  			conf.ProcessField.Path = "target"
   419  			conf.ProcessField.ResultType = test.codec
   420  			conf.ProcessField.Processors = append(conf.ProcessField.Processors, procConf)
   421  
   422  			c, err := New(conf, nil, log.Noop(), metrics.Noop())
   423  			if err != nil {
   424  				tt.Fatal(err)
   425  			}
   426  
   427  			exp := [][]byte{
   428  				[]byte(test.output),
   429  			}
   430  			msg, res := c.ProcessMessage(message.New([][]byte{
   431  				[]byte(test.input),
   432  			}))
   433  			if res != nil {
   434  				tt.Error(res.Error())
   435  			}
   436  			if act := message.GetAllBytes(msg[0]); !reflect.DeepEqual(act, exp) {
   437  				tt.Errorf("Wrong result: %s != %s", act, exp)
   438  			}
   439  		})
   440  	}
   441  }
   442  
   443  func TestProcessFieldBadProc(t *testing.T) {
   444  	conf := NewConfig()
   445  	conf.Type = "process_field"
   446  	conf.ProcessField.Path = "foo.bar"
   447  	conf.ProcessField.Parts = []int{}
   448  
   449  	procConf := NewConfig()
   450  	procConf.Type = "archive"
   451  
   452  	conf.ProcessField.Processors = append(conf.ProcessField.Processors, procConf)
   453  
   454  	c, err := New(conf, nil, log.Noop(), metrics.Noop())
   455  	if err != nil {
   456  		t.Error(err)
   457  		return
   458  	}
   459  
   460  	exp := [][]byte{
   461  		[]byte(`{"foo":{"bar":"encode me"}}`),
   462  		[]byte(`{"foo":{"bar":"encode me too"}}`),
   463  	}
   464  
   465  	msg, res := c.ProcessMessage(message.New(exp))
   466  	if res != nil {
   467  		t.Error(res.Error())
   468  	}
   469  	if act := message.GetAllBytes(msg[0]); !reflect.DeepEqual(act, exp) {
   470  		t.Errorf("Wrong result: %s != %s", act, exp)
   471  	}
   472  }
   473  
   474  func TestProcessFieldBadProcTwo(t *testing.T) {
   475  	conf := NewConfig()
   476  	conf.Type = "process_field"
   477  	conf.ProcessField.Path = "foo.bar"
   478  	conf.ProcessField.Parts = []int{}
   479  
   480  	procConf := NewConfig()
   481  	procConf.Type = "filter"
   482  	procConf.Filter.Type = "static"
   483  	procConf.Filter.Static = false
   484  
   485  	conf.ProcessField.Processors = append(conf.ProcessField.Processors, procConf)
   486  
   487  	c, err := New(conf, nil, log.Noop(), metrics.Noop())
   488  	if err != nil {
   489  		t.Error(err)
   490  		return
   491  	}
   492  
   493  	exp := [][]byte{
   494  		[]byte(`{"foo":{"bar":"encode me"}}`),
   495  		[]byte(`{"foo":{"bar":"encode me too"}}`),
   496  	}
   497  
   498  	msg, res := c.ProcessMessage(message.New(exp))
   499  	if res != nil {
   500  		t.Error(res.Error())
   501  	}
   502  	if act := message.GetAllBytes(msg[0]); !reflect.DeepEqual(act, exp) {
   503  		t.Errorf("Wrong result: %s != %s", act, exp)
   504  	}
   505  }