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 }