github.com/Jeffail/benthos/v3@v3.65.0/lib/processor/unarchive_test.go (about) 1 package processor 2 3 import ( 4 "archive/tar" 5 "archive/zip" 6 "bytes" 7 "fmt" 8 "reflect" 9 "strings" 10 "testing" 11 12 "github.com/Jeffail/benthos/v3/lib/log" 13 "github.com/Jeffail/benthos/v3/lib/message" 14 "github.com/Jeffail/benthos/v3/lib/metrics" 15 ) 16 17 func TestUnarchiveBadAlgo(t *testing.T) { 18 conf := NewConfig() 19 conf.Unarchive.Format = "does not exist" 20 21 testLog := log.Noop() 22 23 _, err := NewUnarchive(conf, nil, testLog, metrics.Noop()) 24 if err == nil { 25 t.Error("Expected error from bad algo") 26 } 27 } 28 29 func TestUnarchiveTar(t *testing.T) { 30 conf := NewConfig() 31 conf.Unarchive.Format = "tar" 32 33 testLog := log.Noop() 34 35 input := [][]byte{ 36 []byte("hello world first part"), 37 []byte("hello world second part"), 38 []byte("third part"), 39 []byte("fourth"), 40 []byte("5"), 41 } 42 43 exp := [][]byte{} 44 expNames := []string{} 45 46 var buf bytes.Buffer 47 tw := tar.NewWriter(&buf) 48 49 for i := range input { 50 exp = append(exp, input[i]) 51 52 hdr := &tar.Header{ 53 Name: fmt.Sprintf("testfile%v", i), 54 Mode: 0o600, 55 Size: int64(len(input[i])), 56 } 57 expNames = append(expNames, hdr.Name) 58 if err := tw.WriteHeader(hdr); err != nil { 59 t.Fatal(err) 60 } 61 if _, err := tw.Write(input[i]); err != nil { 62 t.Fatal(err) 63 } 64 } 65 66 if err := tw.Close(); err != nil { 67 t.Fatal(err) 68 } 69 70 input = [][]byte{buf.Bytes()} 71 72 if reflect.DeepEqual(input, exp) { 73 t.Fatal("Input and exp output are the same") 74 } 75 76 proc, err := NewUnarchive(conf, nil, testLog, metrics.Noop()) 77 if err != nil { 78 t.Fatal(err) 79 } 80 81 msgs, res := proc.ProcessMessage(message.New(input)) 82 if len(msgs) != 1 { 83 t.Errorf("Unarchive failed: %v", res) 84 } else if res != nil { 85 t.Errorf("Expected nil response: %v", res) 86 } 87 if act := message.GetAllBytes(msgs[0]); !reflect.DeepEqual(exp, act) { 88 t.Errorf("Unexpected output: %s != %s", act, exp) 89 } 90 for i := 0; i < msgs[0].Len(); i++ { 91 if name := msgs[0].Get(i).Metadata().Get("archive_filename"); name != expNames[i] { 92 t.Errorf("Unexpected name %d: %s != %s", i, name, expNames[i]) 93 } 94 } 95 } 96 97 func TestUnarchiveZip(t *testing.T) { 98 conf := NewConfig() 99 conf.Unarchive.Format = "zip" 100 101 testLog := log.Noop() 102 103 input := [][]byte{ 104 []byte("hello world first part"), 105 []byte("hello world second part"), 106 []byte("third part"), 107 []byte("fourth"), 108 []byte("5"), 109 } 110 111 exp := [][]byte{} 112 expNames := []string{} 113 114 var buf bytes.Buffer 115 zw := zip.NewWriter(&buf) 116 117 for i := range input { 118 exp = append(exp, input[i]) 119 120 name := fmt.Sprintf("testfile%v", i) 121 expNames = append(expNames, name) 122 if fw, err := zw.Create(name); err != nil { 123 t.Fatal(err) 124 } else if _, err := fw.Write(input[i]); err != nil { 125 t.Fatal(err) 126 } 127 } 128 129 if err := zw.Close(); err != nil { 130 t.Fatal(err) 131 } 132 133 input = [][]byte{buf.Bytes()} 134 135 if reflect.DeepEqual(input, exp) { 136 t.Fatal("Input and exp output are the same") 137 } 138 139 proc, err := NewUnarchive(conf, nil, testLog, metrics.Noop()) 140 if err != nil { 141 t.Fatal(err) 142 } 143 144 msgs, res := proc.ProcessMessage(message.New(input)) 145 if len(msgs) != 1 { 146 t.Errorf("Unarchive failed: %v", res) 147 } else if res != nil { 148 t.Errorf("Expected nil response: %v", res) 149 } 150 if act := message.GetAllBytes(msgs[0]); !reflect.DeepEqual(exp, act) { 151 t.Errorf("Unexpected output: %s != %s", act, exp) 152 } 153 for i := 0; i < msgs[0].Len(); i++ { 154 if name := msgs[0].Get(i).Metadata().Get("archive_filename"); name != expNames[i] { 155 t.Errorf("Unexpected name %d: %s != %s", i, name, expNames[i]) 156 } 157 } 158 } 159 160 func TestUnarchiveLines(t *testing.T) { 161 conf := NewConfig() 162 conf.Unarchive.Format = "lines" 163 164 testLog := log.Noop() 165 166 exp := [][]byte{ 167 []byte("hello world first part"), 168 []byte("hello world second part"), 169 []byte("third part"), 170 []byte("fourth"), 171 []byte("5"), 172 } 173 174 proc, err := NewUnarchive(conf, nil, testLog, metrics.Noop()) 175 if err != nil { 176 t.Fatal(err) 177 } 178 179 msgs, res := proc.ProcessMessage(message.New([][]byte{ 180 []byte(`hello world first part 181 hello world second part 182 third part 183 fourth 184 5`), 185 })) 186 if len(msgs) != 1 { 187 t.Error("Unarchive failed") 188 } else if res != nil { 189 t.Errorf("Expected nil response: %v", res) 190 } 191 if act := message.GetAllBytes(msgs[0]); !reflect.DeepEqual(exp, act) { 192 t.Errorf("Unexpected output: %s != %s", act, exp) 193 } 194 } 195 196 func TestUnarchiveJSONDocuments(t *testing.T) { 197 conf := NewConfig() 198 conf.Unarchive.Format = "json_documents" 199 200 exp := [][]byte{ 201 []byte(`{"foo":"bar"}`), 202 []byte(`5`), 203 []byte(`"testing 123"`), 204 []byte(`["root","is","an","array"]`), 205 []byte(`{"bar":"baz"}`), 206 []byte(`true`), 207 } 208 209 proc, err := NewUnarchive(conf, nil, log.Noop(), metrics.Noop()) 210 if err != nil { 211 t.Fatal(err) 212 } 213 214 msgs, res := proc.ProcessMessage(message.New([][]byte{ 215 []byte(`{"foo":"bar"} 5 "testing 123" ["root", "is", "an", "array"] {"bar": "baz"} true`), 216 })) 217 if len(msgs) != 1 { 218 t.Error("Unarchive failed") 219 } else if res != nil { 220 t.Errorf("Expected nil response: %v", res) 221 } 222 if act := message.GetAllBytes(msgs[0]); !reflect.DeepEqual(exp, act) { 223 t.Errorf("Unexpected output: %s != %s", act, exp) 224 } 225 } 226 227 func TestUnarchiveJSONArray(t *testing.T) { 228 conf := NewConfig() 229 conf.Unarchive.Format = "json_array" 230 231 exp := [][]byte{ 232 []byte(`{"foo":"bar"}`), 233 []byte(`5`), 234 []byte(`"testing 123"`), 235 []byte(`["nested","array"]`), 236 []byte(`true`), 237 } 238 239 proc, err := NewUnarchive(conf, nil, log.Noop(), metrics.Noop()) 240 if err != nil { 241 t.Fatal(err) 242 } 243 244 msgs, res := proc.ProcessMessage(message.New([][]byte{ 245 []byte(`[{"foo":"bar"},5,"testing 123",["nested","array"],true]`), 246 })) 247 if len(msgs) != 1 { 248 t.Error("Unarchive failed") 249 } else if res != nil { 250 t.Errorf("Expected nil response: %v", res) 251 } 252 if act := message.GetAllBytes(msgs[0]); !reflect.DeepEqual(exp, act) { 253 t.Errorf("Unexpected output: %s != %s", act, exp) 254 } 255 } 256 257 func TestUnarchiveJSONMap(t *testing.T) { 258 conf := NewConfig() 259 conf.Unarchive.Format = "json_map" 260 261 exp := [][]byte{ 262 []byte(`{"foo":"bar"}`), 263 []byte(`5`), 264 []byte(`"testing 123"`), 265 []byte(`["nested","array"]`), 266 []byte(`true`), 267 } 268 expKeys := []string{ 269 "a", "b", "c", "d", "e", 270 } 271 272 proc, err := NewUnarchive(conf, nil, log.Noop(), metrics.Noop()) 273 if err != nil { 274 t.Fatal(err) 275 } 276 277 msgs, res := proc.ProcessMessage(message.New([][]byte{ 278 []byte(`{"a":{"foo":"bar"},"b":5,"c":"testing 123","d":["nested","array"],"e":true}`), 279 })) 280 if len(msgs) != 1 { 281 t.Error("Unarchive failed") 282 } else if res != nil { 283 t.Errorf("Expected nil response: %v", res) 284 } else if msgs[0].Len() != len(exp) { 285 t.Errorf("Incorrect number of messages: %d != %d", msgs[0].Len(), len(exp)) 286 } 287 288 // we need to be careful of the random order the map will be generated in 289 // so we can't just test for byte equivalence of the whole array 290 found := make([]bool, msgs[0].Len()) 291 for i := 0; i < msgs[0].Len(); i++ { 292 key := msgs[0].Get(i).Metadata().Get("archive_key") 293 seq := -1 294 for j := 0; j < len(expKeys); j++ { 295 if expKeys[j] == key { 296 seq = j 297 } 298 } 299 if seq < 0 { 300 t.Errorf("Unexpected output: incorrect key %s found in position %d", key, i) 301 } 302 if found[seq] { 303 t.Errorf("Unexpected output: duplicate key %s found in position %d", key, i) 304 } 305 found[seq] = true 306 if act := msgs[0].Get(i).Get(); !reflect.DeepEqual(exp[seq], act) { 307 t.Errorf("Unexpected output: %s != %s", act, exp[seq]) 308 } 309 } 310 for i := 0; i < msgs[0].Len(); i++ { 311 if !found[i] { 312 t.Errorf("Missing output: message for key %s not found", expKeys[i]) 313 } 314 } 315 } 316 317 func TestUnarchiveBinary(t *testing.T) { 318 conf := NewConfig() 319 conf.Unarchive.Format = "binary" 320 321 testLog := log.Noop() 322 proc, err := NewUnarchive(conf, nil, testLog, metrics.Noop()) 323 if err != nil { 324 t.Error(err) 325 return 326 } 327 328 msgs, _ := proc.ProcessMessage( 329 message.New([][]byte{[]byte("wat this isnt good")}), 330 ) 331 if exp, act := 1, len(msgs); exp != act { 332 t.Fatalf("Wrong count: %v != %v", act, exp) 333 } 334 if exp, act := 1, msgs[0].Len(); exp != act { 335 t.Fatalf("Wrong count: %v != %v", act, exp) 336 } 337 if !HasFailed(msgs[0].Get(0)) { 338 t.Error("Expected fail") 339 } 340 341 testMsg := message.New([][]byte{[]byte("hello"), []byte("world")}) 342 testMsgBlob := message.ToBytes(testMsg) 343 344 if msgs, _ := proc.ProcessMessage(message.New([][]byte{testMsgBlob})); len(msgs) == 1 { 345 if !reflect.DeepEqual(message.GetAllBytes(testMsg), message.GetAllBytes(msgs[0])) { 346 t.Errorf("Returned message did not match: %v != %v", msgs, testMsg) 347 } 348 } else { 349 t.Error("Failed on good message") 350 } 351 } 352 353 func TestUnarchiveIndexBounds(t *testing.T) { 354 conf := NewConfig() 355 conf.Unarchive.Format = "tar" 356 357 testLog := log.Noop() 358 359 input := [][]byte{ 360 []byte("0"), 361 []byte("1"), 362 []byte("2"), 363 []byte("3"), 364 []byte("4"), 365 } 366 367 for i := range input { 368 var buf bytes.Buffer 369 tw := tar.NewWriter(&buf) 370 371 hdr := &tar.Header{ 372 Name: fmt.Sprintf("testfile%v", i), 373 Mode: 0o600, 374 Size: int64(len(input[i])), 375 } 376 if err := tw.WriteHeader(hdr); err != nil { 377 t.Fatal(err) 378 } 379 if _, err := tw.Write(input[i]); err != nil { 380 t.Fatal(err) 381 } 382 383 if err := tw.Close(); err != nil { 384 t.Fatal(err) 385 } 386 387 input[i] = buf.Bytes() 388 } 389 390 type result struct { 391 index int 392 value string 393 } 394 395 tests := map[int]result{ 396 -5: { 397 index: 0, 398 value: "0", 399 }, 400 -4: { 401 index: 1, 402 value: "1", 403 }, 404 -3: { 405 index: 2, 406 value: "2", 407 }, 408 -2: { 409 index: 3, 410 value: "3", 411 }, 412 -1: { 413 index: 4, 414 value: "4", 415 }, 416 0: { 417 index: 0, 418 value: "0", 419 }, 420 1: { 421 index: 1, 422 value: "1", 423 }, 424 2: { 425 index: 2, 426 value: "2", 427 }, 428 3: { 429 index: 3, 430 value: "3", 431 }, 432 4: { 433 index: 4, 434 value: "4", 435 }, 436 } 437 438 for i, result := range tests { 439 conf.Unarchive.Parts = []int{i} 440 proc, err := NewUnarchive(conf, nil, testLog, metrics.Noop()) 441 if err != nil { 442 t.Fatal(err) 443 } 444 445 msgs, res := proc.ProcessMessage(message.New(input)) 446 if len(msgs) != 1 { 447 t.Errorf("Unarchive failed on index: %v", i) 448 } else if res != nil { 449 t.Errorf("Expected nil response: %v", res) 450 } 451 if exp, act := result.value, string(message.GetAllBytes(msgs[0])[result.index]); exp != act { 452 t.Errorf("Unexpected output for index %v: %v != %v", i, act, exp) 453 } 454 if exp, act := result.value, string(message.GetAllBytes(msgs[0])[(result.index+1)%5]); exp == act { 455 t.Errorf("Processor was applied to wrong index %v: %v != %v", (result.index+1)%5, act, exp) 456 } 457 } 458 } 459 460 func TestUnarchiveCSV(t *testing.T) { 461 conf := NewConfig() 462 conf.Unarchive.Format = "csv" 463 464 exp := []interface{}{ 465 map[string]interface{}{"id": "1", "name": "foo", "color": "blue"}, 466 map[string]interface{}{"id": "2", "name": "bar", "color": "green"}, 467 map[string]interface{}{"id": "3", "name": "baz", "color": "red"}, 468 } 469 470 proc, err := NewUnarchive(conf, nil, log.Noop(), metrics.Noop()) 471 if err != nil { 472 t.Fatal(err) 473 } 474 475 msgs, res := proc.ProcessMessage(message.New([][]byte{ 476 []byte(strings.Join([]string{ 477 `id,name,color`, 478 `1,foo,blue`, 479 `2,bar,green`, 480 `3,baz,red`, 481 }, "\n")), 482 })) 483 if len(msgs) != 1 { 484 t.Error("Unarchive failed") 485 } else if res != nil { 486 t.Errorf("Expected nil response: %v", res) 487 } 488 489 if msgs[0].Len() != len(exp) { 490 t.Error("Unexpected output: wrong number of items") 491 return 492 } 493 494 for i := 0; i < len(exp); i++ { 495 expPart := exp[i] 496 actPart, err := msgs[0].Get(i).JSON() 497 if err != nil { 498 t.Errorf("Unexpected json error: %v", err) 499 } 500 501 if !reflect.DeepEqual(expPart, actPart) { 502 t.Errorf("Unexpected output: %v != %v", actPart, expPart) 503 } 504 } 505 }