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  }