github.com/Jeffail/benthos/v3@v3.65.0/internal/bloblang/package_test.go (about) 1 package bloblang 2 3 import ( 4 "sync" 5 "testing" 6 7 "github.com/Jeffail/benthos/v3/internal/bloblang/mapping" 8 "github.com/Jeffail/benthos/v3/internal/bloblang/query" 9 "github.com/Jeffail/benthos/v3/lib/message" 10 "github.com/stretchr/testify/assert" 11 "github.com/stretchr/testify/require" 12 ) 13 14 func TestMappings(t *testing.T) { 15 tests := map[string]struct { 16 mapping string 17 input interface{} 18 output interface{} 19 assignmentTargets []mapping.TargetPath 20 queryTargets []query.TargetPath 21 }{ 22 "basic query": { 23 mapping: `root = this.foo 24 let bar = $baz | this.bar.baz`, 25 input: map[string]interface{}{ 26 "foo": "bar", 27 }, 28 output: "bar", 29 assignmentTargets: []mapping.TargetPath{ 30 mapping.NewTargetPath(mapping.TargetValue), 31 mapping.NewTargetPath(mapping.TargetVariable, "bar"), 32 }, 33 queryTargets: []query.TargetPath{ 34 query.NewTargetPath(query.TargetValue, "foo"), 35 query.NewTargetPath(query.TargetVariable, "baz"), 36 query.NewTargetPath(query.TargetValue, "bar", "baz"), 37 }, 38 }, 39 "complex query": { 40 mapping: `root = match this.foo { 41 this.bar == "bruh" => this.baz.buz, 42 _ => $foo 43 }`, 44 input: map[string]interface{}{ 45 "foo": map[string]interface{}{ 46 "bar": "bruh", 47 "baz": map[string]interface{}{ 48 "buz": "the result", 49 }, 50 }, 51 }, 52 output: "the result", 53 assignmentTargets: []mapping.TargetPath{ 54 mapping.NewTargetPath(mapping.TargetValue), 55 }, 56 queryTargets: []query.TargetPath{ 57 query.NewTargetPath(query.TargetValue, "foo", "bar"), 58 query.NewTargetPath(query.TargetValue, "foo", "baz", "buz"), 59 query.NewTargetPath(query.TargetVariable, "foo"), 60 query.NewTargetPath(query.TargetValue, "foo"), 61 }, 62 }, 63 "long assignment": { 64 mapping: `root.foo.bar = "this" 65 root.foo = "that" 66 root.baz.buz.0.bev = "then this"`, 67 output: map[string]interface{}{ 68 "foo": "that", 69 "baz": map[string]interface{}{ 70 "buz": map[string]interface{}{ 71 "0": map[string]interface{}{ 72 "bev": "then this", 73 }, 74 }, 75 }, 76 }, 77 assignmentTargets: []mapping.TargetPath{ 78 mapping.NewTargetPath(mapping.TargetValue, "foo", "bar"), 79 mapping.NewTargetPath(mapping.TargetValue, "foo"), 80 mapping.NewTargetPath(mapping.TargetValue, "baz", "buz", "0", "bev"), 81 }, 82 }, 83 } 84 85 for name, test := range tests { 86 test := test 87 t.Run(name, func(t *testing.T) { 88 m, err := GlobalEnvironment().NewMapping(test.mapping) 89 require.NoError(t, err) 90 91 assert.Equal(t, test.assignmentTargets, m.AssignmentTargets()) 92 93 _, targets := m.QueryTargets(query.TargetsContext{ 94 Maps: map[string]query.Function{}, 95 }) 96 assert.Equal(t, test.queryTargets, targets) 97 98 res, err := m.Exec(query.FunctionContext{ 99 MsgBatch: message.New(nil), 100 Vars: map[string]interface{}{}, 101 }.WithValue(test.input)) 102 require.NoError(t, err) 103 assert.Equal(t, test.output, res) 104 }) 105 } 106 } 107 108 func TestMappingParallelExecution(t *testing.T) { 109 tests := map[string]struct { 110 mapping string 111 input interface{} 112 output interface{} 113 }{ 114 "basic query using vars": { 115 mapping: `let tmp = this.foo.uppercase() 116 root.first = $tmp 117 let tmp = this.foo.lowercase() 118 root.second = $tmp`, 119 input: map[string]interface{}{ 120 "foo": "HELLO world", 121 }, 122 output: map[string]interface{}{ 123 "first": "HELLO WORLD", 124 "second": "hello world", 125 }, 126 }, 127 } 128 129 for name, test := range tests { 130 test := test 131 t.Run(name, func(t *testing.T) { 132 m, err := GlobalEnvironment().NewMapping(test.mapping) 133 require.NoError(t, err) 134 135 startChan := make(chan struct{}) 136 137 var wg sync.WaitGroup 138 for i := 0; i < 10; i++ { 139 wg.Add(1) 140 go func() { 141 defer wg.Done() 142 <-startChan 143 144 for j := 0; j < 100; j++ { 145 part := message.NewPart(nil) 146 require.NoError(t, part.SetJSON(test.input)) 147 148 msg := message.New(nil) 149 msg.Append(part) 150 151 p, err := m.MapPart(0, msg) 152 require.NoError(t, err) 153 154 res, err := p.JSON() 155 require.NoError(t, err) 156 157 assert.Equal(t, test.output, res) 158 } 159 }() 160 } 161 162 close(startChan) 163 wg.Wait() 164 }) 165 } 166 }