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

     1  package processor
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/Jeffail/benthos/v3/lib/log"
     7  	"github.com/Jeffail/benthos/v3/lib/message"
     8  	"github.com/Jeffail/benthos/v3/lib/metrics"
     9  )
    10  
    11  func TestTextValidation(t *testing.T) {
    12  	conf := NewConfig()
    13  	conf.Text.Operator = "dfjjkdsgjkdfhgjfh"
    14  	conf.Text.Parts = []int{0}
    15  	conf.Text.Arg = "foobar"
    16  	conf.Text.Value = "foo"
    17  
    18  	testLog := log.Noop()
    19  
    20  	if _, err := NewText(conf, nil, testLog, metrics.Noop()); err == nil {
    21  		t.Error("Expected error from bad operator")
    22  	}
    23  }
    24  
    25  func TestTextPartBounds(t *testing.T) {
    26  	tLog := log.Noop()
    27  	tStats := metrics.Noop()
    28  
    29  	conf := NewConfig()
    30  	conf.Text.Operator = "trim_space"
    31  
    32  	exp := `foobar`
    33  
    34  	tests := map[int]int{
    35  		-3: 0,
    36  		-2: 1,
    37  		-1: 2,
    38  		0:  0,
    39  		1:  1,
    40  		2:  2,
    41  	}
    42  
    43  	for i, j := range tests {
    44  		input := [][]byte{
    45  			[]byte(`  foobar   `),
    46  			[]byte(`  foobar   `),
    47  			[]byte(`  foobar   `),
    48  		}
    49  
    50  		conf.Text.Parts = []int{i}
    51  		proc, err := NewText(conf, nil, tLog, tStats)
    52  		if err != nil {
    53  			t.Fatal(err)
    54  		}
    55  
    56  		msgs, res := proc.ProcessMessage(message.New(input))
    57  		if len(msgs) != 1 {
    58  			t.Errorf("Select Parts failed on index: %v", i)
    59  		} else if res != nil {
    60  			t.Errorf("Expected nil response: %v", res)
    61  		}
    62  		if act := string(message.GetAllBytes(msgs[0])[j]); exp != act {
    63  			t.Errorf("Unexpected output for index %v: %v != %v", i, act, exp)
    64  		}
    65  		if act := string(message.GetAllBytes(msgs[0])[(j+1)%3]); exp == act {
    66  			t.Errorf("Processor was applied to wrong index %v: %v != %v", (j+1)%3, act, exp)
    67  		}
    68  	}
    69  }
    70  
    71  func TestTextSet(t *testing.T) {
    72  	type jTest struct {
    73  		name   string
    74  		value  string
    75  		input  string
    76  		output string
    77  	}
    78  
    79  	tests := []jTest{
    80  		{
    81  			name:   "set 1",
    82  			value:  `baz`,
    83  			input:  `foo`,
    84  			output: `baz`,
    85  		},
    86  		{
    87  			name:   "set 2",
    88  			value:  `baz`,
    89  			input:  ``,
    90  			output: `baz`,
    91  		},
    92  		{
    93  			name:   "set 3",
    94  			value:  ``,
    95  			input:  `foo`,
    96  			output: ``,
    97  		},
    98  	}
    99  
   100  	for _, test := range tests {
   101  		conf := NewConfig()
   102  		conf.Text.Operator = "set"
   103  		conf.Text.Parts = []int{0}
   104  		conf.Text.Value = test.value
   105  
   106  		tp, err := NewText(conf, nil, log.Noop(), metrics.Noop())
   107  		if err != nil {
   108  			t.Fatalf("Error for test '%v': %v", test.name, err)
   109  		}
   110  
   111  		inMsg := message.New(
   112  			[][]byte{
   113  				[]byte(test.input),
   114  			},
   115  		)
   116  		msgs, _ := tp.ProcessMessage(inMsg)
   117  		if len(msgs) != 1 {
   118  			t.Fatalf("Test '%v' did not succeed", test.name)
   119  		}
   120  
   121  		if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act {
   122  			t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp)
   123  		}
   124  	}
   125  }
   126  
   127  func TestTextAppend(t *testing.T) {
   128  	tLog := log.Noop()
   129  	tStats := metrics.Noop()
   130  
   131  	type jTest struct {
   132  		name   string
   133  		value  string
   134  		input  string
   135  		output string
   136  	}
   137  
   138  	tests := []jTest{
   139  		{
   140  			name:   "append 1",
   141  			value:  `baz`,
   142  			input:  `foo bar `,
   143  			output: `foo bar baz`,
   144  		},
   145  		{
   146  			name:   "append 2",
   147  			value:  ``,
   148  			input:  `foo bar `,
   149  			output: `foo bar `,
   150  		},
   151  		{
   152  			name:   "append 3",
   153  			value:  `baz`,
   154  			input:  ``,
   155  			output: `baz`,
   156  		},
   157  	}
   158  
   159  	for _, test := range tests {
   160  		conf := NewConfig()
   161  		conf.Text.Operator = "append"
   162  		conf.Text.Parts = []int{0}
   163  		conf.Text.Value = test.value
   164  
   165  		tp, err := NewText(conf, nil, tLog, tStats)
   166  		if err != nil {
   167  			t.Fatalf("Error for test '%v': %v", test.name, err)
   168  		}
   169  
   170  		inMsg := message.New(
   171  			[][]byte{
   172  				[]byte(test.input),
   173  			},
   174  		)
   175  		msgs, _ := tp.ProcessMessage(inMsg)
   176  		if len(msgs) != 1 {
   177  			t.Fatalf("Test '%v' did not succeed", test.name)
   178  		}
   179  
   180  		if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act {
   181  			t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp)
   182  		}
   183  	}
   184  }
   185  
   186  func TestTextPrepend(t *testing.T) {
   187  	tLog := log.Noop()
   188  	tStats := metrics.Noop()
   189  
   190  	type jTest struct {
   191  		name   string
   192  		value  string
   193  		input  string
   194  		output string
   195  	}
   196  
   197  	tests := []jTest{
   198  		{
   199  			name:   "prepend 1",
   200  			value:  `baz `,
   201  			input:  `foo bar`,
   202  			output: `baz foo bar`,
   203  		},
   204  		{
   205  			name:   "prepend 2",
   206  			value:  ``,
   207  			input:  `foo bar`,
   208  			output: `foo bar`,
   209  		},
   210  		{
   211  			name:   "prepend 3",
   212  			value:  `baz`,
   213  			input:  ``,
   214  			output: `baz`,
   215  		},
   216  	}
   217  
   218  	for _, test := range tests {
   219  		conf := NewConfig()
   220  		conf.Text.Operator = "prepend"
   221  		conf.Text.Parts = []int{0}
   222  		conf.Text.Value = test.value
   223  
   224  		tp, err := NewText(conf, nil, tLog, tStats)
   225  		if err != nil {
   226  			t.Fatalf("Error for test '%v': %v", test.name, err)
   227  		}
   228  
   229  		inMsg := message.New(
   230  			[][]byte{
   231  				[]byte(test.input),
   232  			},
   233  		)
   234  		msgs, _ := tp.ProcessMessage(inMsg)
   235  		if len(msgs) != 1 {
   236  			t.Fatalf("Test '%v' did not succeed", test.name)
   237  		}
   238  
   239  		if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act {
   240  			t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp)
   241  		}
   242  	}
   243  }
   244  
   245  func TestTextQuote(t *testing.T) {
   246  
   247  	type jTest struct {
   248  		name   string
   249  		input  string
   250  		output string
   251  	}
   252  
   253  	tests := []jTest{
   254  		{
   255  			name:   "quote 1",
   256  			input:  `hello world`,
   257  			output: `"hello world"`,
   258  		},
   259  		{
   260  			name:   "quote 2",
   261  			input:  `"hello", said the world`,
   262  			output: `"\"hello\", said the world"`,
   263  		},
   264  		{
   265  			name:   "quote 3",
   266  			input:  `"hello world"`,
   267  			output: `"\"hello world\""`,
   268  		},
   269  	}
   270  
   271  	for _, test := range tests {
   272  		conf := NewConfig()
   273  		conf.Text.Operator = "quote"
   274  		conf.Text.Parts = []int{0}
   275  
   276  		tp, err := NewText(conf, nil, log.Noop(), metrics.Noop())
   277  		if err != nil {
   278  			t.Fatalf("Error for test '%v': %v", test.name, err)
   279  		}
   280  
   281  		inMsg := message.New(
   282  			[][]byte{
   283  				[]byte(test.input),
   284  			},
   285  		)
   286  		msgs, _ := tp.ProcessMessage(inMsg)
   287  		if len(msgs) != 1 {
   288  			t.Fatalf("Test '%v' did not succeed", test.name)
   289  		}
   290  
   291  		if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act {
   292  			t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp)
   293  		}
   294  	}
   295  }
   296  
   297  func TestTextTrimSpace(t *testing.T) {
   298  	tLog := log.Noop()
   299  	tStats := metrics.Noop()
   300  
   301  	type jTest struct {
   302  		name   string
   303  		input  string
   304  		output string
   305  	}
   306  
   307  	tests := []jTest{
   308  		{
   309  			name:   "trim space 1",
   310  			input:  `foo bar`,
   311  			output: `foo bar`,
   312  		},
   313  		{
   314  			name:   "trim space 2",
   315  			input:  `  foo   bar   `,
   316  			output: `foo   bar`,
   317  		},
   318  		{
   319  			name: "trim space 3",
   320  			input: `
   321  			foo   bar
   322  			`,
   323  			output: `foo   bar`,
   324  		},
   325  	}
   326  
   327  	for _, test := range tests {
   328  		conf := NewConfig()
   329  		conf.Text.Operator = "trim_space"
   330  		conf.Text.Parts = []int{0}
   331  
   332  		tp, err := NewText(conf, nil, tLog, tStats)
   333  		if err != nil {
   334  			t.Fatalf("Error for test '%v': %v", test.name, err)
   335  		}
   336  
   337  		inMsg := message.New(
   338  			[][]byte{
   339  				[]byte(test.input),
   340  			},
   341  		)
   342  		msgs, _ := tp.ProcessMessage(inMsg)
   343  		if len(msgs) != 1 {
   344  			t.Fatalf("Test '%v' did not succeed", test.name)
   345  		}
   346  
   347  		if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act {
   348  			t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp)
   349  		}
   350  	}
   351  }
   352  
   353  func TestTextToUpper(t *testing.T) {
   354  	type jTest struct {
   355  		name   string
   356  		input  string
   357  		output string
   358  	}
   359  
   360  	tests := []jTest{
   361  		{
   362  			name:   "to upper 1",
   363  			input:  `123 hello WORLD @#$`,
   364  			output: `123 HELLO WORLD @#$`,
   365  		},
   366  		{
   367  			name:   "to upper 2",
   368  			input:  `123 HELLO WORLD @#$`,
   369  			output: `123 HELLO WORLD @#$`,
   370  		},
   371  		{
   372  			name:   "to upper 3",
   373  			input:  `123 @#$`,
   374  			output: `123 @#$`,
   375  		},
   376  	}
   377  
   378  	for _, test := range tests {
   379  		conf := NewConfig()
   380  		conf.Text.Operator = "to_upper"
   381  		conf.Text.Parts = []int{0}
   382  
   383  		tp, err := NewText(conf, nil, log.Noop(), metrics.Noop())
   384  		if err != nil {
   385  			t.Fatalf("Error for test '%v': %v", test.name, err)
   386  		}
   387  
   388  		inMsg := message.New(
   389  			[][]byte{
   390  				[]byte(test.input),
   391  			},
   392  		)
   393  		msgs, _ := tp.ProcessMessage(inMsg)
   394  		if len(msgs) != 1 {
   395  			t.Fatalf("Test '%v' did not succeed", test.name)
   396  		}
   397  
   398  		if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act {
   399  			t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp)
   400  		}
   401  	}
   402  }
   403  
   404  func TestTextToLower(t *testing.T) {
   405  	type jTest struct {
   406  		name   string
   407  		input  string
   408  		output string
   409  	}
   410  
   411  	tests := []jTest{
   412  		{
   413  			name:   "to lower 1",
   414  			input:  `123 hello WORLD @#$`,
   415  			output: `123 hello world @#$`,
   416  		},
   417  		{
   418  			name:   "to lower 2",
   419  			input:  `123 hello world @#$`,
   420  			output: `123 hello world @#$`,
   421  		},
   422  		{
   423  			name:   "to lower 3",
   424  			input:  `123 @#$`,
   425  			output: `123 @#$`,
   426  		},
   427  	}
   428  
   429  	for _, test := range tests {
   430  		conf := NewConfig()
   431  		conf.Text.Operator = "to_lower"
   432  		conf.Text.Parts = []int{0}
   433  
   434  		tp, err := NewText(conf, nil, log.Noop(), metrics.Noop())
   435  		if err != nil {
   436  			t.Fatalf("Error for test '%v': %v", test.name, err)
   437  		}
   438  
   439  		inMsg := message.New(
   440  			[][]byte{
   441  				[]byte(test.input),
   442  			},
   443  		)
   444  		msgs, _ := tp.ProcessMessage(inMsg)
   445  		if len(msgs) != 1 {
   446  			t.Fatalf("Test '%v' did not succeed", test.name)
   447  		}
   448  
   449  		if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act {
   450  			t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp)
   451  		}
   452  	}
   453  }
   454  
   455  func TestTextEscapeURLQuery(t *testing.T) {
   456  	type jTest struct {
   457  		name   string
   458  		input  string
   459  		output string
   460  	}
   461  
   462  	tests := []jTest{
   463  		{
   464  			name:   "escape url query 1",
   465  			input:  `foo bar`,
   466  			output: `foo+bar`,
   467  		},
   468  		{
   469  			name:   "escape url query 2",
   470  			input:  `http://foo.bar/wat?this=that`,
   471  			output: `http%3A%2F%2Ffoo.bar%2Fwat%3Fthis%3Dthat`,
   472  		},
   473  		{
   474  			name:   "escape url query 3",
   475  			input:  `foobar`,
   476  			output: `foobar`,
   477  		},
   478  	}
   479  
   480  	for _, test := range tests {
   481  		conf := NewConfig()
   482  		conf.Text.Operator = "escape_url_query"
   483  		conf.Text.Parts = []int{0}
   484  
   485  		tp, err := NewText(conf, nil, log.Noop(), metrics.Noop())
   486  		if err != nil {
   487  			t.Fatalf("Error for test '%v': %v", test.name, err)
   488  		}
   489  
   490  		inMsg := message.New(
   491  			[][]byte{
   492  				[]byte(test.input),
   493  			},
   494  		)
   495  		msgs, _ := tp.ProcessMessage(inMsg)
   496  		if len(msgs) != 1 {
   497  			t.Fatalf("Test '%v' did not succeed", test.name)
   498  		}
   499  
   500  		if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act {
   501  			t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp)
   502  		}
   503  	}
   504  }
   505  
   506  func TestTextUnescapeURLQuery(t *testing.T) {
   507  	type jTest struct {
   508  		name   string
   509  		input  string
   510  		output string
   511  	}
   512  
   513  	tests := []jTest{
   514  		{
   515  			name:   "unescape url query 1",
   516  			input:  `foo+bar`,
   517  			output: `foo bar`,
   518  		},
   519  		{
   520  			name:   "unescape url query 2",
   521  			input:  `http%3A%2F%2Ffoo.bar%2Fwat%3Fthis%3Dthat`,
   522  			output: `http://foo.bar/wat?this=that`,
   523  		},
   524  		{
   525  			name:   "unescape url query 3",
   526  			input:  `foobar`,
   527  			output: `foobar`,
   528  		},
   529  	}
   530  
   531  	for _, test := range tests {
   532  		conf := NewConfig()
   533  		conf.Text.Operator = "unescape_url_query"
   534  		conf.Text.Parts = []int{0}
   535  
   536  		tp, err := NewText(conf, nil, log.Noop(), metrics.Noop())
   537  		if err != nil {
   538  			t.Fatalf("Error for test '%v': %v", test.name, err)
   539  		}
   540  
   541  		inMsg := message.New(
   542  			[][]byte{
   543  				[]byte(test.input),
   544  			},
   545  		)
   546  		msgs, _ := tp.ProcessMessage(inMsg)
   547  		if len(msgs) != 1 {
   548  			t.Fatalf("Test '%v' did not succeed", test.name)
   549  		}
   550  
   551  		if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act {
   552  			t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp)
   553  		}
   554  	}
   555  }
   556  
   557  func TestTextTrim(t *testing.T) {
   558  	tLog := log.Noop()
   559  	tStats := metrics.Noop()
   560  
   561  	type jTest struct {
   562  		name   string
   563  		arg    string
   564  		input  string
   565  		output string
   566  	}
   567  
   568  	tests := []jTest{
   569  		{
   570  			name:   "trim 1",
   571  			arg:    "0",
   572  			input:  `foo bar`,
   573  			output: `foo bar`,
   574  		},
   575  		{
   576  			name:   "trim 2",
   577  			arg:    "0",
   578  			input:  `0foo0bar0`,
   579  			output: `foo0bar`,
   580  		},
   581  		{
   582  			name:   "trim 3",
   583  			arg:    "012",
   584  			input:  `021foo012bar210`,
   585  			output: `foo012bar`,
   586  		},
   587  	}
   588  
   589  	for _, test := range tests {
   590  		conf := NewConfig()
   591  		conf.Text.Operator = "trim"
   592  		conf.Text.Arg = test.arg
   593  		conf.Text.Parts = []int{0}
   594  
   595  		tp, err := NewText(conf, nil, tLog, tStats)
   596  		if err != nil {
   597  			t.Fatalf("Error for test '%v': %v", test.name, err)
   598  		}
   599  
   600  		inMsg := message.New(
   601  			[][]byte{
   602  				[]byte(test.input),
   603  			},
   604  		)
   605  		msgs, _ := tp.ProcessMessage(inMsg)
   606  		if len(msgs) != 1 {
   607  			t.Fatalf("Test '%v' did not succeed", test.name)
   608  		}
   609  
   610  		if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act {
   611  			t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp)
   612  		}
   613  	}
   614  }
   615  
   616  func TestTextRegexpExpand(t *testing.T) {
   617  	tLog := log.Noop()
   618  	tStats := metrics.Noop()
   619  
   620  	type jTest struct {
   621  		name   string
   622  		arg    string
   623  		value  string
   624  		input  string
   625  		output string
   626  	}
   627  
   628  	tests := []jTest{
   629  		{
   630  			name:   "regexp expand 1",
   631  			arg:    "(foo) bar",
   632  			value:  "$1",
   633  			input:  `foo bar`,
   634  			output: `foo`,
   635  		},
   636  		{
   637  			name:   "regexp expand 2",
   638  			arg:    "(?P<key>\\w+) \\w+",
   639  			value:  "$key baz",
   640  			input:  `foo bar`,
   641  			output: `foo baz`,
   642  		},
   643  		{
   644  			name:   "regexp expand 3",
   645  			arg:    "(?m)(?P<key>\\w+):\\s+(?P<value>\\w+)$",
   646  			value:  "$key=$value\n",
   647  			input:  "# comment line\nfoo1: bar1\nbar2: baz2\n\n# another comment line\nbaz3: qux3",
   648  			output: "foo1=bar1\nbar2=baz2\nbaz3=qux3\n",
   649  		},
   650  	}
   651  
   652  	for _, test := range tests {
   653  		conf := NewConfig()
   654  		conf.Text.Operator = "regexp_expand"
   655  		conf.Text.Arg = test.arg
   656  		conf.Text.Value = test.value
   657  		conf.Text.Parts = []int{0}
   658  
   659  		tp, err := NewText(conf, nil, tLog, tStats)
   660  		if err != nil {
   661  			t.Fatalf("Error for test '%v': %v", test.name, err)
   662  		}
   663  
   664  		inMsg := message.New(
   665  			[][]byte{
   666  				[]byte(test.input),
   667  			},
   668  		)
   669  		msgs, _ := tp.ProcessMessage(inMsg)
   670  		if len(msgs) != 1 {
   671  			t.Fatalf("Test '%v' did not succeed", test.name)
   672  		}
   673  
   674  		if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act {
   675  			t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp)
   676  		}
   677  	}
   678  }
   679  
   680  func TestTextReplace(t *testing.T) {
   681  	tLog := log.Noop()
   682  	tStats := metrics.Noop()
   683  
   684  	type jTest struct {
   685  		name   string
   686  		arg    string
   687  		value  string
   688  		input  string
   689  		output string
   690  	}
   691  
   692  	tests := []jTest{
   693  		{
   694  			name:   "replace 1",
   695  			arg:    "foo",
   696  			value:  "bar",
   697  			input:  `foo bar`,
   698  			output: `bar bar`,
   699  		},
   700  		{
   701  			name:   "replace 2",
   702  			arg:    "foo",
   703  			value:  "bar",
   704  			input:  `baz foo bar foo`,
   705  			output: `baz bar bar bar`,
   706  		},
   707  		{
   708  			name:   "replace 3",
   709  			arg:    "foo",
   710  			value:  "bar",
   711  			input:  `baz baz baz baz`,
   712  			output: `baz baz baz baz`,
   713  		},
   714  	}
   715  
   716  	for _, test := range tests {
   717  		conf := NewConfig()
   718  		conf.Text.Operator = "replace"
   719  		conf.Text.Arg = test.arg
   720  		conf.Text.Value = test.value
   721  		conf.Text.Parts = []int{0}
   722  
   723  		tp, err := NewText(conf, nil, tLog, tStats)
   724  		if err != nil {
   725  			t.Fatalf("Error for test '%v': %v", test.name, err)
   726  		}
   727  
   728  		inMsg := message.New(
   729  			[][]byte{
   730  				[]byte(test.input),
   731  			},
   732  		)
   733  		msgs, _ := tp.ProcessMessage(inMsg)
   734  		if len(msgs) != 1 {
   735  			t.Fatalf("Test '%v' did not succeed", test.name)
   736  		}
   737  
   738  		if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act {
   739  			t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp)
   740  		}
   741  	}
   742  }
   743  
   744  func TestTextReplaceRegexp(t *testing.T) {
   745  	tLog := log.Noop()
   746  	tStats := metrics.Noop()
   747  
   748  	type jTest struct {
   749  		name   string
   750  		arg    string
   751  		value  string
   752  		input  string
   753  		output string
   754  	}
   755  
   756  	tests := []jTest{
   757  		{
   758  			name:   "replace regexp 1",
   759  			arg:    "foo?",
   760  			value:  "bar",
   761  			input:  `foo bar`,
   762  			output: `bar bar`,
   763  		},
   764  		{
   765  			name:   "replace regexp 2",
   766  			arg:    "foo?",
   767  			value:  "bar",
   768  			input:  `fo bar`,
   769  			output: `bar bar`,
   770  		},
   771  		{
   772  			name:   "replace regexp 3",
   773  			arg:    "foo?",
   774  			value:  "bar",
   775  			input:  `fooo bar`,
   776  			output: `baro bar`,
   777  		},
   778  		{
   779  			name:   "replace regexp 4",
   780  			arg:    "foo?",
   781  			value:  "bar",
   782  			input:  `baz bar`,
   783  			output: `baz bar`,
   784  		},
   785  		{
   786  			name:   "replace regexp submatch 1",
   787  			arg:    "(foo?) (bar?) (baz?)",
   788  			value:  "hello $2 world",
   789  			input:  `foo bar baz`,
   790  			output: `hello bar world`,
   791  		},
   792  		{
   793  			name:   "replace regexp submatch 2",
   794  			arg:    "(foo?) (bar?) (baz?)",
   795  			value:  "hello $4 world",
   796  			input:  `foo bar baz`,
   797  			output: `hello  world`,
   798  		},
   799  	}
   800  
   801  	for _, test := range tests {
   802  		conf := NewConfig()
   803  		conf.Text.Operator = "replace_regexp"
   804  		conf.Text.Arg = test.arg
   805  		conf.Text.Value = test.value
   806  		conf.Text.Parts = []int{0}
   807  
   808  		tp, err := NewText(conf, nil, tLog, tStats)
   809  		if err != nil {
   810  			t.Fatalf("Error for test '%v': %v", test.name, err)
   811  		}
   812  
   813  		inMsg := message.New(
   814  			[][]byte{
   815  				[]byte(test.input),
   816  			},
   817  		)
   818  		msgs, _ := tp.ProcessMessage(inMsg)
   819  		if len(msgs) != 1 {
   820  			t.Fatalf("Test '%v' did not succeed", test.name)
   821  		}
   822  
   823  		if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act {
   824  			t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp)
   825  		}
   826  	}
   827  }
   828  
   829  func TestTextFindRegexp(t *testing.T) {
   830  	type jTest struct {
   831  		name   string
   832  		arg    string
   833  		input  string
   834  		output string
   835  	}
   836  
   837  	tests := []jTest{
   838  		{
   839  			name:   "find regexp 1",
   840  			arg:    "foo?",
   841  			input:  `foo bar`,
   842  			output: `foo`,
   843  		},
   844  		{
   845  			name:   "find regexp 2",
   846  			arg:    "foo?",
   847  			input:  `fo bar`,
   848  			output: `fo`,
   849  		},
   850  		{
   851  			name:   "find regexp 3",
   852  			arg:    "foo?",
   853  			input:  `fooo bar`,
   854  			output: `foo`,
   855  		},
   856  		{
   857  			name:   "find regexp 4",
   858  			arg:    "foo?",
   859  			input:  `baz bar`,
   860  			output: ``,
   861  		},
   862  	}
   863  
   864  	for _, test := range tests {
   865  		conf := NewConfig()
   866  		conf.Text.Operator = "find_regexp"
   867  		conf.Text.Arg = test.arg
   868  		conf.Text.Parts = []int{0}
   869  
   870  		tp, err := NewText(conf, nil, log.Noop(), metrics.Noop())
   871  		if err != nil {
   872  			t.Fatalf("Error for test '%v': %v", test.name, err)
   873  		}
   874  
   875  		inMsg := message.New(
   876  			[][]byte{
   877  				[]byte(test.input),
   878  			},
   879  		)
   880  		msgs, _ := tp.ProcessMessage(inMsg)
   881  		if len(msgs) != 1 {
   882  			t.Fatalf("Test '%v' did not succeed", test.name)
   883  		}
   884  
   885  		if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act {
   886  			t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp)
   887  		}
   888  	}
   889  }
   890  
   891  func TestTextStripHTML(t *testing.T) {
   892  	tLog := log.Noop()
   893  	tStats := metrics.Noop()
   894  
   895  	type jTest struct {
   896  		name   string
   897  		input  string
   898  		output string
   899  	}
   900  
   901  	tests := []jTest{
   902  		{
   903  			name:   "strip html 1",
   904  			input:  `foo <a>bar</a>`,
   905  			output: `foo bar`,
   906  		},
   907  		{
   908  			name:   "strip html 2",
   909  			input:  `<div>foo <a>bar</a></div>`,
   910  			output: `foo bar`,
   911  		},
   912  		{
   913  			name:   "strip html 3",
   914  			input:  `<div field="bar">foo <a>bar</a></div>`,
   915  			output: `foo bar`,
   916  		},
   917  		{
   918  			name:   "strip html 4",
   919  			input:  `<div field="bar">foo<broken <a>bar</a>`,
   920  			output: `foobar`,
   921  		},
   922  	}
   923  
   924  	for _, test := range tests {
   925  		conf := NewConfig()
   926  		conf.Text.Operator = "strip_html"
   927  		conf.Text.Parts = []int{0}
   928  
   929  		tp, err := NewText(conf, nil, tLog, tStats)
   930  		if err != nil {
   931  			t.Fatalf("Error for test '%v': %v", test.name, err)
   932  		}
   933  
   934  		inMsg := message.New(
   935  			[][]byte{
   936  				[]byte(test.input),
   937  			},
   938  		)
   939  		msgs, _ := tp.ProcessMessage(inMsg)
   940  		if len(msgs) != 1 {
   941  			t.Fatalf("Test '%v' did not succeed", test.name)
   942  		}
   943  
   944  		if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act {
   945  			t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp)
   946  		}
   947  	}
   948  }
   949  
   950  func TestTextUnquote(t *testing.T) {
   951  
   952  	type jTest struct {
   953  		name   string
   954  		input  string
   955  		output string
   956  	}
   957  
   958  	tests := []jTest{
   959  		{
   960  			name:   "unquote 1",
   961  			input:  `"hello world"`,
   962  			output: `hello world`,
   963  		},
   964  		{
   965  			name:   "unquote 2",
   966  			input:  `"\"hello\", said the world"`,
   967  			output: `"hello", said the world`,
   968  		},
   969  		{
   970  			name:   "unquote 3",
   971  			input:  `"\"hello world\""`,
   972  			output: `"hello world"`,
   973  		},
   974  	}
   975  
   976  	for _, test := range tests {
   977  		conf := NewConfig()
   978  		conf.Text.Operator = "unquote"
   979  		conf.Text.Parts = []int{0}
   980  
   981  		tp, err := NewText(conf, nil, log.Noop(), metrics.Noop())
   982  		if err != nil {
   983  			t.Fatalf("Error for test '%v': %v", test.name, err)
   984  		}
   985  
   986  		inMsg := message.New(
   987  			[][]byte{
   988  				[]byte(test.input),
   989  			},
   990  		)
   991  		msgs, _ := tp.ProcessMessage(inMsg)
   992  		if len(msgs) != 1 {
   993  			t.Fatalf("Test '%v' did not succeed", test.name)
   994  		}
   995  
   996  		if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act {
   997  			t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp)
   998  		}
   999  	}
  1000  }