funcs_misc_test.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. // Copyright 2022-2023 EMQ Technologies Co., Ltd.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package function
  15. import (
  16. "errors"
  17. "fmt"
  18. "reflect"
  19. "testing"
  20. "time"
  21. "github.com/stretchr/testify/assert"
  22. "github.com/stretchr/testify/require"
  23. "github.com/lf-edge/ekuiper/internal/conf"
  24. "github.com/lf-edge/ekuiper/internal/keyedstate"
  25. "github.com/lf-edge/ekuiper/internal/testx"
  26. kctx "github.com/lf-edge/ekuiper/internal/topo/context"
  27. "github.com/lf-edge/ekuiper/internal/topo/state"
  28. "github.com/lf-edge/ekuiper/pkg/api"
  29. "github.com/lf-edge/ekuiper/pkg/ast"
  30. )
  31. func init() {
  32. testx.InitEnv()
  33. }
  34. func TestToMap(t *testing.T) {
  35. f, ok := builtins["object_construct"]
  36. if !ok {
  37. t.Fatal("builtin not found")
  38. }
  39. contextLogger := conf.Log.WithField("rule", "testExec")
  40. ctx := kctx.WithValue(kctx.Background(), kctx.LoggerKey, contextLogger)
  41. tempStore, _ := state.CreateStore("mockRule0", api.AtMostOnce)
  42. fctx := kctx.NewDefaultFuncContext(ctx.WithMeta("mockRule0", "test", tempStore), 2)
  43. tests := []struct {
  44. args []interface{}
  45. result interface{}
  46. }{
  47. { // 0
  48. args: []interface{}{
  49. "foo",
  50. "bar",
  51. },
  52. result: map[string]interface{}{
  53. "foo": "bar",
  54. },
  55. }, { // 1
  56. args: []interface{}{
  57. true,
  58. "bar",
  59. },
  60. result: fmt.Errorf("key true is not a string"),
  61. }, { // 2
  62. args: []interface{}{
  63. "key1",
  64. "bar",
  65. "key2",
  66. "foo",
  67. },
  68. result: map[string]interface{}{
  69. "key1": "bar",
  70. "key2": "foo",
  71. },
  72. },
  73. }
  74. for i, tt := range tests {
  75. result, _ := f.exec(fctx, tt.args)
  76. if !reflect.DeepEqual(result, tt.result) {
  77. t.Errorf("%d result mismatch,\ngot:\t%v \nwant:\t%v", i, result, tt.result)
  78. }
  79. }
  80. }
  81. func TestCoalesceExec(t *testing.T) {
  82. f, ok := builtins["coalesce"]
  83. if !ok {
  84. t.Fatal("builtin not found")
  85. }
  86. contextLogger := conf.Log.WithField("rule", "testExec")
  87. ctx := kctx.WithValue(kctx.Background(), kctx.LoggerKey, contextLogger)
  88. tempStore, _ := state.CreateStore("mockRule0", api.AtMostOnce)
  89. fctx := kctx.NewDefaultFuncContext(ctx.WithMeta("mockRule0", "test", tempStore), 2)
  90. tests := []struct {
  91. args []interface{}
  92. result interface{}
  93. }{
  94. { // 1
  95. args: []interface{}{
  96. "foo",
  97. "bar",
  98. "2",
  99. },
  100. result: "foo",
  101. },
  102. { // 2
  103. args: []interface{}{
  104. nil,
  105. "dd",
  106. "1",
  107. },
  108. result: "dd",
  109. },
  110. { // 3
  111. args: []interface{}{
  112. "bar",
  113. nil,
  114. "1",
  115. },
  116. result: "bar",
  117. },
  118. { // 4
  119. args: []interface{}{
  120. nil,
  121. nil,
  122. "2",
  123. },
  124. result: "2",
  125. },
  126. { // 4
  127. args: []interface{}{
  128. nil,
  129. nil,
  130. nil,
  131. },
  132. result: nil,
  133. },
  134. }
  135. for i, tt := range tests {
  136. result, _ := f.exec(fctx, tt.args)
  137. if !reflect.DeepEqual(result, tt.result) {
  138. t.Errorf("%d result mismatch,\ngot:\t%v \nwant:\t%v", i, result, tt.result)
  139. }
  140. }
  141. }
  142. func TestToSeconds(t *testing.T) {
  143. f, ok := builtins["to_seconds"]
  144. if !ok {
  145. t.Fatal("builtin not found")
  146. }
  147. contextLogger := conf.Log.WithField("rule", "testExec")
  148. ctx := kctx.WithValue(kctx.Background(), kctx.LoggerKey, contextLogger)
  149. tempStore, _ := state.CreateStore("mockRule0", api.AtMostOnce)
  150. fctx := kctx.NewDefaultFuncContext(ctx.WithMeta("mockRule0", "test", tempStore), 2)
  151. tests := []struct {
  152. args []interface{}
  153. result interface{}
  154. }{
  155. { // 0
  156. args: []interface{}{
  157. time.Unix(1e9, 0),
  158. },
  159. result: int64(1e9),
  160. }, { // 1
  161. args: []interface{}{
  162. nil,
  163. },
  164. result: errors.New("unsupported type to convert to timestamp <nil>"),
  165. },
  166. }
  167. for _, tt := range tests {
  168. result, _ := f.exec(fctx, tt.args)
  169. assert.Equal(t, tt.result, result)
  170. }
  171. }
  172. func TestToJson(t *testing.T) {
  173. f, ok := builtins["to_json"]
  174. if !ok {
  175. t.Fatal("builtin not found")
  176. }
  177. contextLogger := conf.Log.WithField("rule", "testExec")
  178. ctx := kctx.WithValue(kctx.Background(), kctx.LoggerKey, contextLogger)
  179. tempStore, _ := state.CreateStore("mockRule0", api.AtMostOnce)
  180. fctx := kctx.NewDefaultFuncContext(ctx.WithMeta("mockRule0", "test", tempStore), 2)
  181. tests := []struct {
  182. args []interface{}
  183. result interface{}
  184. }{
  185. { // 0
  186. args: []interface{}{
  187. "foo",
  188. },
  189. result: `"foo"`,
  190. }, { // 1
  191. args: []interface{}{
  192. nil,
  193. },
  194. result: "null",
  195. }, { // 2
  196. args: []interface{}{
  197. map[string]interface{}{
  198. "key1": "bar",
  199. "key2": "foo",
  200. },
  201. },
  202. result: `{"key1":"bar","key2":"foo"}`,
  203. },
  204. }
  205. for i, tt := range tests {
  206. result, _ := f.exec(fctx, tt.args)
  207. if !reflect.DeepEqual(result, tt.result) {
  208. t.Errorf("%d result mismatch,\ngot:\t%v \nwant:\t%v", i, result, tt.result)
  209. }
  210. }
  211. }
  212. func TestFromJson(t *testing.T) {
  213. f, ok := builtins["parse_json"]
  214. if !ok {
  215. t.Fatal("builtin not found")
  216. }
  217. contextLogger := conf.Log.WithField("rule", "testExec")
  218. ctx := kctx.WithValue(kctx.Background(), kctx.LoggerKey, contextLogger)
  219. tempStore, _ := state.CreateStore("mockRule0", api.AtMostOnce)
  220. fctx := kctx.NewDefaultFuncContext(ctx.WithMeta("mockRule0", "test", tempStore), 2)
  221. tests := []struct {
  222. args []interface{}
  223. result interface{}
  224. }{
  225. { // 0
  226. args: []interface{}{
  227. `"foo"`,
  228. },
  229. result: "foo",
  230. }, { // 1
  231. args: []interface{}{
  232. "null",
  233. },
  234. result: nil,
  235. }, { // 2
  236. args: []interface{}{
  237. `{"key1":"bar","key2":"foo"}`,
  238. },
  239. result: map[string]interface{}{
  240. "key1": "bar",
  241. "key2": "foo",
  242. },
  243. }, { // 3
  244. args: []interface{}{
  245. "key1",
  246. },
  247. result: fmt.Errorf("fail to parse json: invalid character 'k' looking for beginning of value"),
  248. }, { // 4
  249. args: []interface{}{
  250. `[{"key1":"bar","key2":"foo"}]`,
  251. },
  252. result: []interface{}{
  253. map[string]interface{}{
  254. "key1": "bar",
  255. "key2": "foo",
  256. },
  257. },
  258. },
  259. }
  260. for i, tt := range tests {
  261. result, _ := f.exec(fctx, tt.args)
  262. if !reflect.DeepEqual(result, tt.result) {
  263. t.Errorf("%d result mismatch,\ngot:\t%v \nwant:\t%v", i, result, tt.result)
  264. }
  265. }
  266. }
  267. func TestConvertTZ(t *testing.T) {
  268. f, ok := builtins["convert_tz"]
  269. if !ok {
  270. t.Fatal("builtin not found")
  271. }
  272. contextLogger := conf.Log.WithField("rule", "testExec")
  273. ctx := kctx.WithValue(kctx.Background(), kctx.LoggerKey, contextLogger)
  274. tempStore, _ := state.CreateStore("mockRule0", api.AtMostOnce)
  275. fctx := kctx.NewDefaultFuncContext(ctx.WithMeta("mockRule0", "test", tempStore), 2)
  276. loc, _ := time.LoadLocation("Asia/Shanghai")
  277. tests := []struct {
  278. args []interface{}
  279. result interface{}
  280. }{
  281. { // 0
  282. args: []interface{}{
  283. time.Date(2022, time.April, 13, 6, 22, 32, 233000000, time.UTC),
  284. "UTC",
  285. },
  286. result: time.Date(2022, time.April, 13, 6, 22, 32, 233000000, time.UTC),
  287. }, { // 1
  288. args: []interface{}{
  289. time.Date(2022, time.April, 13, 6, 22, 32, 233000000, time.UTC),
  290. "Asia/Shanghai",
  291. },
  292. result: time.Date(2022, time.April, 13, 14, 22, 32, 233000000, loc),
  293. }, { // 2
  294. args: []interface{}{
  295. time.Date(2022, time.April, 13, 6, 22, 32, 233000000, time.UTC),
  296. "Unknown",
  297. },
  298. result: errors.New("unknown time zone Unknown"),
  299. }, { // 3
  300. args: []interface{}{
  301. true,
  302. "UTC",
  303. },
  304. result: errors.New("unsupported type to convert to timestamp true"),
  305. },
  306. }
  307. for _, tt := range tests {
  308. result, _ := f.exec(fctx, tt.args)
  309. assert.Equal(t, tt.result, result)
  310. }
  311. vtests := []struct {
  312. args []ast.Expr
  313. wantErr bool
  314. }{
  315. {
  316. []ast.Expr{&ast.TimeLiteral{Val: 0}, &ast.StringLiteral{Val: "0"}},
  317. false,
  318. },
  319. {
  320. []ast.Expr{&ast.StringLiteral{Val: "0"}},
  321. true,
  322. },
  323. {
  324. []ast.Expr{&ast.NumberLiteral{Val: 0}, &ast.NumberLiteral{Val: 0}},
  325. true,
  326. },
  327. {
  328. []ast.Expr{&ast.NumberLiteral{Val: 0}, &ast.TimeLiteral{Val: 0}},
  329. true,
  330. },
  331. {
  332. []ast.Expr{&ast.NumberLiteral{Val: 0}, &ast.BooleanLiteral{Val: true}},
  333. true,
  334. },
  335. {
  336. []ast.Expr{&ast.StringLiteral{Val: "0"}, &ast.NumberLiteral{Val: 0}},
  337. true,
  338. },
  339. {
  340. []ast.Expr{&ast.BooleanLiteral{Val: true}, &ast.NumberLiteral{Val: 0}},
  341. true,
  342. },
  343. }
  344. for _, vtt := range vtests {
  345. err := f.val(fctx, vtt.args)
  346. if vtt.wantErr {
  347. assert.Error(t, err)
  348. } else {
  349. assert.NoError(t, err)
  350. }
  351. }
  352. }
  353. func TestDelay(t *testing.T) {
  354. f, ok := builtins["delay"]
  355. if !ok {
  356. t.Fatal("builtin not found")
  357. }
  358. contextLogger := conf.Log.WithField("rule", "testExec")
  359. ctx := kctx.WithValue(kctx.Background(), kctx.LoggerKey, contextLogger)
  360. tempStore, _ := state.CreateStore("mockRule0", api.AtMostOnce)
  361. fctx := kctx.NewDefaultFuncContext(ctx.WithMeta("mockRule0", "test", tempStore), 2)
  362. err := f.val(fctx, []ast.Expr{&ast.StringLiteral{Val: "abc"}})
  363. if err == nil {
  364. t.Fatal("expect error")
  365. }
  366. err = f.val(fctx, []ast.Expr{&ast.StringLiteral{Val: "1s"}, &ast.StringLiteral{Val: "1s"}})
  367. if err == nil {
  368. t.Fatal("expect error")
  369. }
  370. err = f.val(fctx, []ast.Expr{&ast.IntegerLiteral{Val: 1000}, &ast.StringLiteral{Val: "1s"}})
  371. if err != nil {
  372. t.Fatal("expect no error")
  373. }
  374. tests := []struct {
  375. args []interface{}
  376. result interface{}
  377. }{
  378. { // 0
  379. args: []interface{}{
  380. 10,
  381. "bar",
  382. },
  383. result: "bar",
  384. }, { // 1
  385. args: []interface{}{
  386. "bar",
  387. "bar",
  388. },
  389. result: fmt.Errorf("cannot convert string(bar) to int"),
  390. },
  391. }
  392. for i, tt := range tests {
  393. result, _ := f.exec(fctx, tt.args)
  394. if !reflect.DeepEqual(result, tt.result) {
  395. t.Errorf("%d result mismatch,\ngot:\t%v \nwant:\t%v", i, result, tt.result)
  396. }
  397. }
  398. }
  399. func TestKeyedStateValidation(t *testing.T) {
  400. f, ok := builtins["get_keyed_state"]
  401. if !ok {
  402. t.Fatal("builtin not found")
  403. }
  404. tests := []struct {
  405. args []ast.Expr
  406. err error
  407. }{
  408. {
  409. args: []ast.Expr{
  410. &ast.StringLiteral{Val: "foo"},
  411. },
  412. err: fmt.Errorf("Expect 3 arguments but found 1."),
  413. }, {
  414. args: []ast.Expr{
  415. &ast.StringLiteral{Val: "foo"},
  416. &ast.StringLiteral{Val: "bar"},
  417. },
  418. err: fmt.Errorf("Expect 3 arguments but found 2."),
  419. }, {
  420. args: []ast.Expr{
  421. &ast.StringLiteral{Val: "foo"},
  422. &ast.StringLiteral{Val: "bar"},
  423. &ast.StringLiteral{Val: "barz"},
  424. },
  425. err: fmt.Errorf("expect one of following value for the 2nd parameter: bigint, float, string, boolean, datetime"),
  426. }, {
  427. args: []ast.Expr{
  428. &ast.StringLiteral{Val: "foo"},
  429. &ast.StringLiteral{Val: "bigint"},
  430. &ast.StringLiteral{Val: "barz"},
  431. },
  432. err: nil,
  433. },
  434. }
  435. for i, tt := range tests {
  436. err := f.val(nil, tt.args)
  437. if !reflect.DeepEqual(err, tt.err) {
  438. t.Errorf("%d result mismatch,\ngot:\t%v \nwant:\t%v", i, err, tt.err)
  439. }
  440. }
  441. }
  442. func TestKeyedStateExec(t *testing.T) {
  443. keyedstate.InitKeyedStateKV()
  444. f, ok := builtins["get_keyed_state"]
  445. if !ok {
  446. t.Fatal("builtin not found")
  447. }
  448. contextLogger := conf.Log.WithField("rule", "testExec")
  449. ctx := kctx.WithValue(kctx.Background(), kctx.LoggerKey, contextLogger)
  450. tempStore, _ := state.CreateStore("mockRule0", api.AtMostOnce)
  451. fctx := kctx.NewDefaultFuncContext(ctx.WithMeta("mockRule0", "test", tempStore), 1)
  452. tests := []struct {
  453. args []interface{}
  454. result interface{}
  455. }{
  456. { // 0
  457. args: []interface{}{
  458. "foo",
  459. },
  460. result: fmt.Errorf("the args must be two or three"),
  461. }, { // 1
  462. args: []interface{}{
  463. "foo",
  464. "bigint",
  465. "baz",
  466. "bar",
  467. },
  468. result: fmt.Errorf("the args must be two or three"),
  469. }, { // 2
  470. args: []interface{}{
  471. "foo",
  472. "float",
  473. 20.0,
  474. },
  475. result: 20.0,
  476. },
  477. }
  478. for i, tt := range tests {
  479. result, _ := f.exec(fctx, tt.args)
  480. if !reflect.DeepEqual(result, tt.result) {
  481. t.Errorf("%d result mismatch,\ngot:\t%v \nwant:\t%v", i, result, tt.result)
  482. }
  483. }
  484. _ = keyedstate.ClearKeyedState()
  485. }
  486. func TestHexIntFunctions(t *testing.T) {
  487. contextLogger := conf.Log.WithField("rule", "testExec")
  488. ctx := kctx.WithValue(kctx.Background(), kctx.LoggerKey, contextLogger)
  489. tempStore, _ := state.CreateStore("mockRule0", api.AtMostOnce)
  490. fctx := kctx.NewDefaultFuncContext(ctx.WithMeta("mockRule0", "test", tempStore), 2)
  491. tests := []struct {
  492. name string
  493. args []interface{}
  494. result interface{}
  495. }{
  496. {
  497. name: "hex2dec",
  498. args: []interface{}{
  499. "0x10",
  500. },
  501. result: int64(16),
  502. },
  503. {
  504. name: "dec2hex",
  505. args: []interface{}{
  506. 16,
  507. },
  508. result: "0x10",
  509. },
  510. }
  511. for i, tt := range tests {
  512. f, ok := builtins[tt.name]
  513. if !ok {
  514. t.Fatal(fmt.Sprintf("builtin %v not found", tt.name))
  515. }
  516. result, _ := f.exec(fctx, tt.args)
  517. if !reflect.DeepEqual(result, tt.result) {
  518. t.Errorf("%d result mismatch,\ngot:\t%v \nwant:\t%v", i, result, tt.result)
  519. }
  520. }
  521. }
  522. func TestMiscFuncNil(t *testing.T) {
  523. contextLogger := conf.Log.WithField("rule", "testExec")
  524. ctx := kctx.WithValue(kctx.Background(), kctx.LoggerKey, contextLogger)
  525. tempStore, _ := state.CreateStore("mockRule0", api.AtMostOnce)
  526. fctx := kctx.NewDefaultFuncContext(ctx.WithMeta("mockRule0", "test", tempStore), 2)
  527. oldBuiltins := builtins
  528. defer func() {
  529. builtins = oldBuiltins
  530. }()
  531. builtins = map[string]builtinFunc{}
  532. registerMiscFunc()
  533. for name, function := range builtins {
  534. switch name {
  535. case "compress", "decompress", "newuuid", "tstamp", "rule_id", "rule_start", "window_start", "window_end", "event_time",
  536. "json_path_query", "json_path_query_first", "coalesce", "meta", "json_path_exists":
  537. continue
  538. case "isnull":
  539. v, b := function.exec(fctx, []interface{}{nil})
  540. require.True(t, b)
  541. require.Equal(t, v, true)
  542. case "cardinality":
  543. v, b := function.check([]interface{}{nil})
  544. require.True(t, b)
  545. require.Equal(t, v, 0)
  546. case "to_json":
  547. v, b := function.exec(fctx, []interface{}{nil})
  548. require.True(t, b)
  549. require.Equal(t, v, "null")
  550. case "parse_json":
  551. v, b := function.exec(fctx, []interface{}{nil})
  552. require.True(t, b)
  553. require.Equal(t, v, nil)
  554. v, b = function.exec(fctx, []interface{}{"null"})
  555. require.True(t, b)
  556. require.Equal(t, v, nil)
  557. default:
  558. v, b := function.check([]interface{}{nil})
  559. require.True(t, b, fmt.Sprintf("%v failed", name))
  560. require.Nil(t, v, fmt.Sprintf("%v failed", name))
  561. }
  562. }
  563. }
  564. func TestCast(t *testing.T) {
  565. f, ok := builtins["cast"]
  566. if !ok {
  567. t.Fatal("builtin not found")
  568. }
  569. contextLogger := conf.Log.WithField("rule", "testExec")
  570. ctx := kctx.WithValue(kctx.Background(), kctx.LoggerKey, contextLogger)
  571. tempStore, _ := state.CreateStore("mockRule0", api.AtMostOnce)
  572. fctx := kctx.NewDefaultFuncContext(ctx.WithMeta("mockRule0", "test", tempStore), 2)
  573. tests := []struct {
  574. args []interface{}
  575. result interface{}
  576. }{
  577. { // 0
  578. args: []interface{}{
  579. "Ynl0ZWE=",
  580. "bytea",
  581. },
  582. result: []byte("bytea"),
  583. },
  584. { // 1
  585. args: []interface{}{
  586. []byte("bytea"),
  587. "bytea",
  588. },
  589. result: []byte("bytea"),
  590. },
  591. { // 2
  592. args: []interface{}{
  593. 1,
  594. "bytea",
  595. },
  596. result: fmt.Errorf("cannot convert int(1) to bytea"),
  597. },
  598. { // 3
  599. args: []interface{}{
  600. 101.5,
  601. "bigint",
  602. },
  603. result: 101,
  604. },
  605. { // 4
  606. args: []interface{}{
  607. 1,
  608. "boolean",
  609. },
  610. result: true,
  611. },
  612. { // 5
  613. args: []interface{}{
  614. 1,
  615. "float",
  616. },
  617. result: float64(1),
  618. },
  619. { // 6
  620. args: []interface{}{
  621. 1,
  622. "string",
  623. },
  624. result: "1",
  625. },
  626. }
  627. for _, tt := range tests {
  628. result, _ := f.exec(fctx, tt.args)
  629. assert.Equal(t, tt.result, result)
  630. }
  631. vtests := []struct {
  632. args []ast.Expr
  633. wantErr bool
  634. }{
  635. {
  636. []ast.Expr{&ast.FieldRef{Name: "foo"}, &ast.StringLiteral{Val: "bytea"}},
  637. false,
  638. },
  639. {
  640. []ast.Expr{&ast.FieldRef{Name: "foo"}},
  641. true,
  642. },
  643. {
  644. []ast.Expr{&ast.FieldRef{Name: "foo"}, &ast.StringLiteral{Val: "bigint"}},
  645. false,
  646. },
  647. {
  648. []ast.Expr{&ast.FieldRef{Name: "foo"}, &ast.StringLiteral{Val: "float"}},
  649. false,
  650. },
  651. {
  652. []ast.Expr{&ast.FieldRef{Name: "foo"}, &ast.StringLiteral{Val: "string"}},
  653. false,
  654. },
  655. {
  656. []ast.Expr{&ast.FieldRef{Name: "foo"}, &ast.StringLiteral{Val: "boolean"}},
  657. false,
  658. },
  659. {
  660. []ast.Expr{&ast.FieldRef{Name: "foo"}, &ast.StringLiteral{Val: "test"}},
  661. true,
  662. },
  663. }
  664. for _, vtt := range vtests {
  665. err := f.val(fctx, vtt.args)
  666. if vtt.wantErr {
  667. assert.Error(t, err)
  668. } else {
  669. assert.NoError(t, err)
  670. }
  671. }
  672. }