github.com/Jeffail/benthos/v3@v3.65.0/public/service/message_test.go (about)

     1  package service
     2  
     3  import (
     4  	"errors"
     5  	"testing"
     6  
     7  	ibloblang "github.com/Jeffail/benthos/v3/internal/bloblang"
     8  	"github.com/Jeffail/benthos/v3/lib/message"
     9  	"github.com/Jeffail/benthos/v3/public/bloblang"
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/require"
    12  )
    13  
    14  func TestMessageCopyAirGap(t *testing.T) {
    15  	p := message.NewPart([]byte("hello world"))
    16  	p.Metadata().Set("foo", "bar")
    17  	g1 := newMessageFromPart(p)
    18  	g2 := g1.Copy()
    19  
    20  	b := p.Get()
    21  	v := p.Metadata().Get("foo")
    22  	assert.Equal(t, "hello world", string(b))
    23  	assert.Equal(t, "bar", v)
    24  
    25  	b, err := g1.AsBytes()
    26  	v, _ = g1.MetaGet("foo")
    27  	require.NoError(t, err)
    28  	assert.Equal(t, "hello world", string(b))
    29  	assert.Equal(t, "bar", v)
    30  
    31  	b, err = g2.AsBytes()
    32  	v, _ = g2.MetaGet("foo")
    33  	require.NoError(t, err)
    34  	assert.Equal(t, "hello world", string(b))
    35  	assert.Equal(t, "bar", v)
    36  
    37  	g2.SetBytes([]byte("and now this"))
    38  	g2.MetaSet("foo", "baz")
    39  
    40  	b = p.Get()
    41  	v = p.Metadata().Get("foo")
    42  	assert.Equal(t, "hello world", string(b))
    43  	assert.Equal(t, "bar", v)
    44  
    45  	b, err = g1.AsBytes()
    46  	v, _ = g1.MetaGet("foo")
    47  	require.NoError(t, err)
    48  	assert.Equal(t, "hello world", string(b))
    49  	assert.Equal(t, "bar", v)
    50  
    51  	b, err = g2.AsBytes()
    52  	v, _ = g2.MetaGet("foo")
    53  	require.NoError(t, err)
    54  	assert.Equal(t, "and now this", string(b))
    55  	assert.Equal(t, "baz", v)
    56  
    57  	g1.SetBytes([]byte("but not this"))
    58  	g1.MetaSet("foo", "buz")
    59  
    60  	b = p.Get()
    61  	v = p.Metadata().Get("foo")
    62  	assert.Equal(t, "hello world", string(b))
    63  	assert.Equal(t, "bar", v)
    64  
    65  	b, err = g1.AsBytes()
    66  	v, _ = g1.MetaGet("foo")
    67  	require.NoError(t, err)
    68  	assert.Equal(t, "but not this", string(b))
    69  	assert.Equal(t, "buz", v)
    70  
    71  	b, err = g2.AsBytes()
    72  	v, _ = g2.MetaGet("foo")
    73  	require.NoError(t, err)
    74  	assert.Equal(t, "and now this", string(b))
    75  	assert.Equal(t, "baz", v)
    76  }
    77  
    78  func TestMessageQuery(t *testing.T) {
    79  	p := message.NewPart([]byte(`{"foo":"bar"}`))
    80  	p.Metadata().Set("foo", "bar")
    81  	p.Metadata().Set("bar", "baz")
    82  	g1 := newMessageFromPart(p)
    83  
    84  	b, err := g1.AsBytes()
    85  	assert.NoError(t, err)
    86  	assert.Equal(t, `{"foo":"bar"}`, string(b))
    87  
    88  	s, err := g1.AsStructured()
    89  	assert.NoError(t, err)
    90  	assert.Equal(t, map[string]interface{}{"foo": "bar"}, s)
    91  
    92  	m, ok := g1.MetaGet("foo")
    93  	assert.True(t, ok)
    94  	assert.Equal(t, "bar", m)
    95  
    96  	seen := map[string]string{}
    97  	err = g1.MetaWalk(func(k, v string) error {
    98  		seen[k] = v
    99  		return errors.New("stop")
   100  	})
   101  	assert.EqualError(t, err, "stop")
   102  	assert.Len(t, seen, 1)
   103  
   104  	seen = map[string]string{}
   105  	err = g1.MetaWalk(func(k, v string) error {
   106  		seen[k] = v
   107  		return nil
   108  	})
   109  	assert.NoError(t, err)
   110  	assert.Equal(t, map[string]string{
   111  		"foo": "bar",
   112  		"bar": "baz",
   113  	}, seen)
   114  }
   115  
   116  func TestMessageMutate(t *testing.T) {
   117  	p := message.NewPart([]byte(`not a json doc`))
   118  	p.Metadata().Set("foo", "bar")
   119  	p.Metadata().Set("bar", "baz")
   120  	g1 := newMessageFromPart(p)
   121  
   122  	_, err := g1.AsStructured()
   123  	assert.Error(t, err)
   124  
   125  	g1.SetStructured(map[string]interface{}{
   126  		"foo": "bar",
   127  	})
   128  	assert.Equal(t, "not a json doc", string(p.Get()))
   129  
   130  	s, err := g1.AsStructured()
   131  	assert.NoError(t, err)
   132  	assert.Equal(t, map[string]interface{}{
   133  		"foo": "bar",
   134  	}, s)
   135  
   136  	g1.SetBytes([]byte("foo bar baz"))
   137  	assert.Equal(t, "not a json doc", string(p.Get()))
   138  
   139  	_, err = g1.AsStructured()
   140  	assert.Error(t, err)
   141  
   142  	b, err := g1.AsBytes()
   143  	assert.NoError(t, err)
   144  	assert.Equal(t, "foo bar baz", string(b))
   145  
   146  	g1.MetaDelete("foo")
   147  
   148  	seen := map[string]string{}
   149  	err = g1.MetaWalk(func(k, v string) error {
   150  		seen[k] = v
   151  		return nil
   152  	})
   153  	assert.NoError(t, err)
   154  	assert.Equal(t, map[string]string{"bar": "baz"}, seen)
   155  
   156  	g1.MetaSet("foo", "new bar")
   157  
   158  	seen = map[string]string{}
   159  	err = g1.MetaWalk(func(k, v string) error {
   160  		seen[k] = v
   161  		return nil
   162  	})
   163  	assert.NoError(t, err)
   164  	assert.Equal(t, map[string]string{"foo": "new bar", "bar": "baz"}, seen)
   165  }
   166  
   167  func TestNewMessageMutate(t *testing.T) {
   168  	g0 := NewMessage([]byte(`not a json doc`))
   169  	g0.MetaSet("foo", "bar")
   170  	g0.MetaSet("bar", "baz")
   171  
   172  	g1 := g0.Copy()
   173  
   174  	_, err := g1.AsStructured()
   175  	assert.Error(t, err)
   176  
   177  	g1.SetStructured(map[string]interface{}{
   178  		"foo": "bar",
   179  	})
   180  	g0Bytes, err := g0.AsBytes()
   181  	require.NoError(t, err)
   182  	assert.Equal(t, "not a json doc", string(g0Bytes))
   183  
   184  	s, err := g1.AsStructuredMut()
   185  	assert.NoError(t, err)
   186  	assert.Equal(t, map[string]interface{}{
   187  		"foo": "bar",
   188  	}, s)
   189  
   190  	g1.SetBytes([]byte("foo bar baz"))
   191  	g0Bytes, err = g0.AsBytes()
   192  	require.NoError(t, err)
   193  	assert.Equal(t, "not a json doc", string(g0Bytes))
   194  
   195  	_, err = g1.AsStructured()
   196  	assert.Error(t, err)
   197  
   198  	b, err := g1.AsBytes()
   199  	assert.NoError(t, err)
   200  	assert.Equal(t, "foo bar baz", string(b))
   201  
   202  	g1.MetaDelete("foo")
   203  
   204  	seen := map[string]string{}
   205  	err = g1.MetaWalk(func(k, v string) error {
   206  		seen[k] = v
   207  		return nil
   208  	})
   209  	assert.NoError(t, err)
   210  	assert.Equal(t, map[string]string{"bar": "baz"}, seen)
   211  
   212  	g1.MetaSet("foo", "new bar")
   213  
   214  	seen = map[string]string{}
   215  	err = g1.MetaWalk(func(k, v string) error {
   216  		seen[k] = v
   217  		return nil
   218  	})
   219  	assert.NoError(t, err)
   220  	assert.Equal(t, map[string]string{"foo": "new bar", "bar": "baz"}, seen)
   221  }
   222  
   223  func TestMessageMapping(t *testing.T) {
   224  	part := NewMessage(nil)
   225  	part.SetStructured(map[string]interface{}{
   226  		"content": "hello world",
   227  	})
   228  
   229  	blobl, err := bloblang.Parse("root.new_content = this.content.uppercase()")
   230  	require.NoError(t, err)
   231  
   232  	res, err := part.BloblangQuery(blobl)
   233  	require.NoError(t, err)
   234  
   235  	resI, err := res.AsStructured()
   236  	require.NoError(t, err)
   237  	assert.Equal(t, map[string]interface{}{
   238  		"new_content": "HELLO WORLD",
   239  	}, resI)
   240  }
   241  
   242  func TestMessageBatchMapping(t *testing.T) {
   243  	partOne := NewMessage(nil)
   244  	partOne.SetStructured(map[string]interface{}{
   245  		"content": "hello world 1",
   246  	})
   247  
   248  	partTwo := NewMessage(nil)
   249  	partTwo.SetStructured(map[string]interface{}{
   250  		"content": "hello world 2",
   251  	})
   252  
   253  	blobl, err := bloblang.Parse(`root.new_content = json("content").from_all().join(" - ")`)
   254  	require.NoError(t, err)
   255  
   256  	res, err := MessageBatch{partOne, partTwo}.BloblangQuery(0, blobl)
   257  	require.NoError(t, err)
   258  
   259  	resI, err := res.AsStructured()
   260  	require.NoError(t, err)
   261  	assert.Equal(t, map[string]interface{}{
   262  		"new_content": "hello world 1 - hello world 2",
   263  	}, resI)
   264  }
   265  
   266  func BenchmarkMessageMappingNew(b *testing.B) {
   267  	part := NewMessage(nil)
   268  	part.SetStructured(map[string]interface{}{
   269  		"content": "hello world",
   270  	})
   271  
   272  	blobl, err := bloblang.Parse("root.new_content = this.content.uppercase()")
   273  	require.NoError(b, err)
   274  
   275  	b.ResetTimer()
   276  	b.ReportAllocs()
   277  
   278  	for i := 0; i < b.N; i++ {
   279  		res, err := part.BloblangQuery(blobl)
   280  		require.NoError(b, err)
   281  
   282  		resI, err := res.AsStructured()
   283  		require.NoError(b, err)
   284  		assert.Equal(b, map[string]interface{}{
   285  			"new_content": "HELLO WORLD",
   286  		}, resI)
   287  	}
   288  }
   289  
   290  func BenchmarkMessageMappingOld(b *testing.B) {
   291  	part := message.NewPart(nil)
   292  	require.NoError(b, part.SetJSON(map[string]interface{}{
   293  		"content": "hello world",
   294  	}))
   295  
   296  	msg := message.New(nil)
   297  	msg.Append(part)
   298  
   299  	blobl, err := ibloblang.GlobalEnvironment().NewMapping("root.new_content = this.content.uppercase()")
   300  	require.NoError(b, err)
   301  
   302  	b.ResetTimer()
   303  	b.ReportAllocs()
   304  
   305  	for i := 0; i < b.N; i++ {
   306  		res, err := blobl.MapPart(0, msg)
   307  		require.NoError(b, err)
   308  
   309  		resI, err := res.JSON()
   310  		require.NoError(b, err)
   311  		assert.Equal(b, map[string]interface{}{
   312  			"new_content": "HELLO WORLD",
   313  		}, resI)
   314  	}
   315  }