jsonextract_test.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. package exprhelpers
  2. import (
  3. "testing"
  4. log "github.com/sirupsen/logrus"
  5. "github.com/antonmedv/expr"
  6. "github.com/stretchr/testify/assert"
  7. "github.com/stretchr/testify/require"
  8. )
  9. func TestJsonExtract(t *testing.T) {
  10. if err := Init(nil); err != nil {
  11. log.Fatal(err)
  12. }
  13. err := FileInit(TestFolder, "test_data_re.txt", "regex")
  14. if err != nil {
  15. log.Fatal(err)
  16. }
  17. tests := []struct {
  18. name string
  19. jsonBlob string
  20. targetField string
  21. expectResult string
  22. expr string
  23. }{
  24. {
  25. name: "basic json extract",
  26. jsonBlob: `{"test" : "1234"}`,
  27. targetField: "test",
  28. expectResult: "1234",
  29. expr: "JsonExtract(blob, target)",
  30. },
  31. {
  32. name: "basic json extract with non existing field",
  33. jsonBlob: `{"test" : "1234"}`,
  34. targetField: "non_existing_field",
  35. expectResult: "",
  36. expr: "JsonExtract(blob, target)",
  37. },
  38. {
  39. name: "extract subfield",
  40. jsonBlob: `{"test" : {"a": "b"}}`,
  41. targetField: "test.a",
  42. expectResult: "b",
  43. expr: "JsonExtract(blob, target)",
  44. },
  45. }
  46. for _, test := range tests {
  47. t.Run(test.name, func(t *testing.T) {
  48. env := map[string]interface{}{
  49. "blob": test.jsonBlob,
  50. "target": test.targetField,
  51. }
  52. vm, err := expr.Compile(test.expr, GetExprOptions(env)...)
  53. require.NoError(t, err)
  54. out, err := expr.Run(vm, env)
  55. require.NoError(t, err)
  56. assert.Equal(t, test.expectResult, out)
  57. })
  58. }
  59. }
  60. func TestJsonExtractUnescape(t *testing.T) {
  61. if err := Init(nil); err != nil {
  62. log.Fatal(err)
  63. }
  64. err := FileInit(TestFolder, "test_data_re.txt", "regex")
  65. if err != nil {
  66. log.Fatal(err)
  67. }
  68. tests := []struct {
  69. name string
  70. jsonBlob string
  71. targetField string
  72. expectResult string
  73. expr string
  74. }{
  75. {
  76. name: "basic json extract",
  77. jsonBlob: `{"log" : "\"GET /JBNwtQ6i.blt HTTP/1.1\" 200 13 \"-\" \"Craftbot\""}`,
  78. targetField: "log",
  79. expectResult: "\"GET /JBNwtQ6i.blt HTTP/1.1\" 200 13 \"-\" \"Craftbot\"",
  80. expr: "JsonExtractUnescape(blob, target)",
  81. },
  82. {
  83. name: "basic json extract with non existing field",
  84. jsonBlob: `{"test" : "1234"}`,
  85. targetField: "non_existing_field",
  86. expectResult: "",
  87. expr: "JsonExtractUnescape(blob, target)",
  88. },
  89. }
  90. for _, test := range tests {
  91. t.Run(test.name, func(t *testing.T) {
  92. env := map[string]interface{}{
  93. "blob": test.jsonBlob,
  94. "target": test.targetField,
  95. }
  96. vm, err := expr.Compile(test.expr, GetExprOptions(env)...)
  97. require.NoError(t, err)
  98. out, err := expr.Run(vm, env)
  99. require.NoError(t, err)
  100. assert.Equal(t, test.expectResult, out)
  101. })
  102. }
  103. }
  104. func TestJsonExtractSlice(t *testing.T) {
  105. if err := Init(nil); err != nil {
  106. log.Fatal(err)
  107. }
  108. err := FileInit(TestFolder, "test_data_re.txt", "regex")
  109. if err != nil {
  110. log.Fatal(err)
  111. }
  112. tests := []struct {
  113. name string
  114. jsonBlob string
  115. targetField string
  116. expectResult []interface{}
  117. expr string
  118. }{
  119. {
  120. name: "try to extract a string as a slice",
  121. jsonBlob: `{"test" : "1234"}`,
  122. targetField: "test",
  123. expectResult: nil,
  124. expr: "JsonExtractSlice(blob, target)",
  125. },
  126. {
  127. name: "basic json slice extract",
  128. jsonBlob: `{"test" : ["1234"]}`,
  129. targetField: "test",
  130. expectResult: []interface{}{"1234"},
  131. expr: "JsonExtractSlice(blob, target)",
  132. },
  133. {
  134. name: "extract with complex expression",
  135. jsonBlob: `{"test": {"foo": [{"a":"b"}]}}`,
  136. targetField: "test.foo",
  137. expectResult: []interface{}{map[string]interface{}{"a": "b"}},
  138. expr: "JsonExtractSlice(blob, target)",
  139. },
  140. {
  141. name: "extract non-existing key",
  142. jsonBlob: `{"test: "11234"}`,
  143. targetField: "foo",
  144. expectResult: nil,
  145. expr: "JsonExtractSlice(blob, target)",
  146. },
  147. }
  148. for _, test := range tests {
  149. test := test
  150. t.Run(test.name, func(t *testing.T) {
  151. env := map[string]interface{}{
  152. "blob": test.jsonBlob,
  153. "target": test.targetField,
  154. }
  155. vm, err := expr.Compile(test.expr, GetExprOptions(env)...)
  156. require.NoError(t, err)
  157. out, err := expr.Run(vm, env)
  158. require.NoError(t, err)
  159. assert.Equal(t, test.expectResult, out)
  160. })
  161. }
  162. }
  163. func TestJsonExtractObject(t *testing.T) {
  164. if err := Init(nil); err != nil {
  165. log.Fatal(err)
  166. }
  167. err := FileInit(TestFolder, "test_data_re.txt", "regex")
  168. if err != nil {
  169. log.Fatal(err)
  170. }
  171. tests := []struct {
  172. name string
  173. jsonBlob string
  174. targetField string
  175. expectResult map[string]interface{}
  176. expr string
  177. }{
  178. {
  179. name: "try to extract a string as an object",
  180. jsonBlob: `{"test" : "1234"}`,
  181. targetField: "test",
  182. expectResult: nil,
  183. expr: "JsonExtractObject(blob, target)",
  184. },
  185. {
  186. name: "basic json object extract",
  187. jsonBlob: `{"test" : {"1234": {"foo": "bar"}}}`,
  188. targetField: "test",
  189. expectResult: map[string]interface{}{"1234": map[string]interface{}{"foo": "bar"}},
  190. expr: "JsonExtractObject(blob, target)",
  191. },
  192. {
  193. name: "extract with complex expression",
  194. jsonBlob: `{"test": {"foo": [{"a":"b"}]}}`,
  195. targetField: "test.foo[0]",
  196. expectResult: map[string]interface{}{"a": "b"},
  197. expr: "JsonExtractObject(blob, target)",
  198. },
  199. }
  200. for _, test := range tests {
  201. test := test
  202. t.Run(test.name, func(t *testing.T) {
  203. env := map[string]interface{}{
  204. "blob": test.jsonBlob,
  205. "target": test.targetField,
  206. }
  207. vm, err := expr.Compile(test.expr, GetExprOptions(env)...)
  208. require.NoError(t, err)
  209. out, err := expr.Run(vm, env)
  210. require.NoError(t, err)
  211. assert.Equal(t, test.expectResult, out)
  212. })
  213. }
  214. }
  215. func TestToJson(t *testing.T) {
  216. err := Init(nil)
  217. require.NoError(t, err)
  218. tests := []struct {
  219. name string
  220. obj interface{}
  221. expectResult string
  222. expr string
  223. }{
  224. {
  225. name: "convert int",
  226. obj: 42,
  227. expectResult: "42",
  228. expr: "ToJsonString(obj)",
  229. },
  230. {
  231. name: "convert slice",
  232. obj: []string{"foo", "bar"},
  233. expectResult: `["foo","bar"]`,
  234. expr: "ToJsonString(obj)",
  235. },
  236. {
  237. name: "convert map",
  238. obj: map[string]string{"foo": "bar"},
  239. expectResult: `{"foo":"bar"}`,
  240. expr: "ToJsonString(obj)",
  241. },
  242. {
  243. name: "convert struct",
  244. obj: struct{ Foo string }{"bar"},
  245. expectResult: `{"Foo":"bar"}`,
  246. expr: "ToJsonString(obj)",
  247. },
  248. {
  249. name: "convert complex struct",
  250. obj: struct {
  251. Foo string
  252. Bar struct {
  253. Baz string
  254. }
  255. Bla []string
  256. }{
  257. Foo: "bar",
  258. Bar: struct {
  259. Baz string
  260. }{
  261. Baz: "baz",
  262. },
  263. Bla: []string{"foo", "bar"},
  264. },
  265. expectResult: `{"Foo":"bar","Bar":{"Baz":"baz"},"Bla":["foo","bar"]}`,
  266. expr: "ToJsonString(obj)",
  267. },
  268. {
  269. name: "convert invalid type",
  270. obj: func() {},
  271. expectResult: "",
  272. expr: "ToJsonString(obj)",
  273. },
  274. }
  275. for _, test := range tests {
  276. t.Run(test.name, func(t *testing.T) {
  277. env := map[string]interface{}{
  278. "obj": test.obj,
  279. }
  280. vm, err := expr.Compile(test.expr, GetExprOptions(env)...)
  281. require.NoError(t, err)
  282. out, err := expr.Run(vm, env)
  283. require.NoError(t, err)
  284. assert.Equal(t, test.expectResult, out)
  285. })
  286. }
  287. }
  288. func TestUnmarshalJSON(t *testing.T) {
  289. err := Init(nil)
  290. require.NoError(t, err)
  291. tests := []struct {
  292. name string
  293. json string
  294. expectResult interface{}
  295. expr string
  296. }{
  297. {
  298. name: "convert int",
  299. json: "42",
  300. expectResult: float64(42),
  301. expr: "UnmarshalJSON(json, out, 'a')",
  302. },
  303. {
  304. name: "convert slice",
  305. json: `["foo","bar"]`,
  306. expectResult: []interface{}{"foo", "bar"},
  307. expr: "UnmarshalJSON(json, out, 'a')",
  308. },
  309. {
  310. name: "convert map",
  311. json: `{"foo":"bar"}`,
  312. expectResult: map[string]interface{}{"foo": "bar"},
  313. expr: "UnmarshalJSON(json, out, 'a')",
  314. },
  315. {
  316. name: "convert struct",
  317. json: `{"Foo":"bar"}`,
  318. expectResult: map[string]interface{}{"Foo": "bar"},
  319. expr: "UnmarshalJSON(json, out, 'a')",
  320. },
  321. {
  322. name: "convert complex struct",
  323. json: `{"Foo":"bar","Bar":{"Baz":"baz"},"Bla":["foo","bar"]}`,
  324. expectResult: map[string]interface{}{
  325. "Foo": "bar",
  326. "Bar": map[string]interface{}{
  327. "Baz": "baz",
  328. },
  329. "Bla": []interface{}{"foo", "bar"},
  330. },
  331. expr: "UnmarshalJSON(json, out, 'a')",
  332. },
  333. }
  334. for _, test := range tests {
  335. t.Run(test.name, func(t *testing.T) {
  336. outMap := make(map[string]interface{})
  337. env := map[string]interface{}{
  338. "json": test.json,
  339. "out": outMap,
  340. }
  341. vm, err := expr.Compile(test.expr, GetExprOptions(env)...)
  342. require.NoError(t, err)
  343. _, err = expr.Run(vm, env)
  344. require.NoError(t, err)
  345. assert.Equal(t, test.expectResult, outMap["a"])
  346. })
  347. }
  348. }