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 }