github.com/Jeffail/benthos/v3@v3.65.0/lib/processor/jmespath_test.go (about) 1 package processor 2 3 import ( 4 "strconv" 5 "testing" 6 7 "github.com/Jeffail/benthos/v3/lib/log" 8 "github.com/Jeffail/benthos/v3/lib/message" 9 "github.com/Jeffail/benthos/v3/lib/metrics" 10 "github.com/Jeffail/gabs/v2" 11 ) 12 13 func TestJMESPathAllParts(t *testing.T) { 14 conf := NewConfig() 15 conf.JMESPath.Parts = []int{} 16 conf.JMESPath.Query = "foo.bar" 17 18 testLog := log.Noop() 19 20 jSet, err := NewJMESPath(conf, nil, testLog, metrics.Noop()) 21 if err != nil { 22 t.Fatal(err) 23 } 24 25 msgIn := message.New([][]byte{ 26 []byte(`{"foo":{"bar":0}}`), 27 []byte(`{"foo":{"bar":1}}`), 28 []byte(`{"foo":{"bar":2}}`), 29 }) 30 msgs, res := jSet.ProcessMessage(msgIn) 31 if len(msgs) != 1 { 32 t.Fatal("Wrong count of messages") 33 } 34 if res != nil { 35 t.Fatal("Non-nil result") 36 } 37 for i, part := range message.GetAllBytes(msgs[0]) { 38 if exp, act := strconv.Itoa(i), string(part); exp != act { 39 t.Errorf("Wrong output from json: %v != %v", act, exp) 40 } 41 } 42 } 43 44 func TestJMESPathValidation(t *testing.T) { 45 conf := NewConfig() 46 conf.JMESPath.Parts = []int{0} 47 conf.JMESPath.Query = "foo.bar" 48 49 testLog := log.Noop() 50 51 jSet, err := NewJMESPath(conf, nil, testLog, metrics.Noop()) 52 if err != nil { 53 t.Fatal(err) 54 } 55 56 msgIn := message.New([][]byte{[]byte("this is bad json")}) 57 msgs, res := jSet.ProcessMessage(msgIn) 58 if len(msgs) != 1 { 59 t.Fatal("No passthrough for bad input data") 60 } 61 if res != nil { 62 t.Fatal("Non-nil result") 63 } 64 if exp, act := "this is bad json", string(message.GetAllBytes(msgs[0])[0]); exp != act { 65 t.Errorf("Wrong output from bad json: %v != %v", act, exp) 66 } 67 68 conf.JMESPath.Parts = []int{5} 69 70 jSet, err = NewJMESPath(conf, nil, testLog, metrics.Noop()) 71 if err != nil { 72 t.Fatal(err) 73 } 74 75 msgIn = message.New([][]byte{[]byte("{}")}) 76 msgs, res = jSet.ProcessMessage(msgIn) 77 if len(msgs) != 1 { 78 t.Fatal("No passthrough for bad index") 79 } 80 if res != nil { 81 t.Fatal("Non-nil result") 82 } 83 if exp, act := "{}", string(message.GetAllBytes(msgs[0])[0]); exp != act { 84 t.Errorf("Wrong output from bad index: %v != %v", act, exp) 85 } 86 } 87 88 func TestJMESPathMutation(t *testing.T) { 89 conf := NewConfig() 90 conf.JMESPath.Query = "{foo: merge(foo, {bar:'baz'})}" 91 92 jSet, err := NewJMESPath(conf, nil, log.Noop(), metrics.Noop()) 93 if err != nil { 94 t.Fatal(err) 95 } 96 97 ogObj := gabs.New() 98 ogObj.Set("is this", "foo", "original", "content") 99 ogExp := ogObj.String() 100 101 msgIn := message.New(make([][]byte, 1)) 102 msgIn.Get(0).SetJSON(ogObj.Data()) 103 msgs, res := jSet.ProcessMessage(msgIn) 104 if len(msgs) != 1 { 105 t.Fatal("No passthrough for bad input data") 106 } 107 if res != nil { 108 t.Fatal("Non-nil result") 109 } 110 if exp, act := `{"foo":{"bar":"baz","original":{"content":"is this"}}}`, string(message.GetAllBytes(msgs[0])[0]); exp != act { 111 t.Errorf("Wrong output: %v != %v", act, exp) 112 } 113 114 if exp, act := ogExp, ogObj.String(); exp != act { 115 t.Errorf("Original contents were mutated: %v != %v", act, exp) 116 } 117 } 118 119 func TestJMESPath(t *testing.T) { 120 tLog := log.Noop() 121 tStats := metrics.Noop() 122 123 type jTest struct { 124 name string 125 path string 126 input string 127 output string 128 } 129 130 tests := []jTest{ 131 { 132 name: "select obj", 133 path: "foo.bar", 134 input: `{"foo":{"bar":{"baz":1}}}`, 135 output: `{"baz":1}`, 136 }, 137 { 138 name: "select array", 139 path: "foo.bar", 140 input: `{"foo":{"bar":["baz","qux"]}}`, 141 output: `["baz","qux"]`, 142 }, 143 { 144 name: "select obj as str", 145 path: "foo.bar", 146 input: `{"foo":{"bar":"{\"baz\":1}"}}`, 147 output: `"{\"baz\":1}"`, 148 }, 149 { 150 name: "select str", 151 path: "foo.bar", 152 input: `{"foo":{"bar":"hello world"}}`, 153 output: `"hello world"`, 154 }, 155 { 156 name: "select float", 157 path: "foo.bar", 158 input: `{"foo":{"bar":0.123}}`, 159 output: `0.123`, 160 }, 161 { 162 name: "select int", 163 path: "foo.bar", 164 input: `{"foo":{"bar":123}}`, 165 output: `123`, 166 }, 167 { 168 name: "select bool", 169 path: "foo.bar", 170 input: `{"foo":{"bar":true}}`, 171 output: `true`, 172 }, 173 { 174 name: "addition int", 175 path: "sum([foo.bar, `6`])", 176 input: `{"foo":{"bar":123}}`, 177 output: `129`, 178 }, 179 } 180 181 for _, test := range tests { 182 conf := NewConfig() 183 conf.JMESPath.Parts = []int{0} 184 conf.JMESPath.Query = test.path 185 186 jSet, err := NewJMESPath(conf, nil, tLog, tStats) 187 if err != nil { 188 t.Fatalf("Error for test '%v': %v", test.name, err) 189 } 190 191 inMsg := message.New( 192 [][]byte{ 193 []byte(test.input), 194 }, 195 ) 196 msgs, _ := jSet.ProcessMessage(inMsg) 197 if len(msgs) != 1 { 198 t.Fatalf("Test '%v' did not succeed", test.name) 199 } 200 201 if exp, act := test.output, string(message.GetAllBytes(msgs[0])[0]); exp != act { 202 t.Errorf("Wrong result '%v': %v != %v", test.name, act, exp) 203 } 204 } 205 }