rule_test.go 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118
  1. // Copyright 2021-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 topotest
  15. import (
  16. "encoding/json"
  17. "testing"
  18. "github.com/lf-edge/ekuiper/internal/topo/topotest/mocknode"
  19. "github.com/lf-edge/ekuiper/pkg/api"
  20. )
  21. func TestWindowFuncSQL(t *testing.T) {
  22. // Reset
  23. streamList := []string{"demo"}
  24. HandleStream(false, streamList, t)
  25. tests := []RuleTest{
  26. {
  27. Name: "TestRowNumber1",
  28. Sql: `select size, row_number() from demo`,
  29. R: [][]map[string]interface{}{
  30. {
  31. {
  32. "row_number": float64(1),
  33. "size": float64(3),
  34. },
  35. },
  36. {
  37. {
  38. "row_number": float64(1),
  39. "size": float64(6),
  40. },
  41. },
  42. {
  43. {
  44. "row_number": float64(1),
  45. "size": float64(2),
  46. },
  47. },
  48. {
  49. {
  50. "row_number": float64(1),
  51. "size": float64(4),
  52. },
  53. },
  54. {
  55. {
  56. "row_number": float64(1),
  57. "size": float64(1),
  58. },
  59. },
  60. },
  61. },
  62. {
  63. Name: "TestRowNumber2",
  64. Sql: `select size, row_number() from demo group by countWindow(5)`,
  65. R: [][]map[string]interface{}{
  66. {
  67. {
  68. "row_number": float64(1),
  69. "size": float64(3),
  70. },
  71. {
  72. "row_number": float64(2),
  73. "size": float64(6),
  74. },
  75. {
  76. "row_number": float64(3),
  77. "size": float64(2),
  78. },
  79. {
  80. "row_number": float64(4),
  81. "size": float64(4),
  82. },
  83. {
  84. "row_number": float64(5),
  85. "size": float64(1),
  86. },
  87. },
  88. },
  89. },
  90. }
  91. // Data setup
  92. HandleStream(true, streamList, t)
  93. options := []*api.RuleOption{
  94. {
  95. BufferLength: 100,
  96. SendError: true,
  97. },
  98. {
  99. BufferLength: 100,
  100. SendError: true,
  101. Qos: api.AtLeastOnce,
  102. CheckpointInterval: 5000,
  103. },
  104. {
  105. BufferLength: 100,
  106. SendError: true,
  107. Qos: api.ExactlyOnce,
  108. CheckpointInterval: 5000,
  109. },
  110. }
  111. for j, opt := range options {
  112. DoRuleTest(t, tests, j, opt, 0)
  113. }
  114. }
  115. func TestAccAggSQL(t *testing.T) {
  116. // Reset
  117. streamList := []string{"demo"}
  118. HandleStream(false, streamList, t)
  119. tests := []RuleTest{
  120. {
  121. Name: "TestAccAggSql1",
  122. Sql: `select acc_sum(size) over (partition by color), color from demo`,
  123. R: [][]map[string]interface{}{
  124. {
  125. {
  126. "acc_sum": float64(3),
  127. "color": "red",
  128. },
  129. },
  130. {
  131. {
  132. "acc_sum": float64(6),
  133. "color": "blue",
  134. },
  135. },
  136. {
  137. {
  138. "acc_sum": float64(8),
  139. "color": "blue",
  140. },
  141. },
  142. {
  143. {
  144. "acc_sum": float64(4),
  145. "color": "yellow",
  146. },
  147. },
  148. {
  149. {
  150. "acc_sum": float64(4),
  151. "color": "red",
  152. },
  153. },
  154. },
  155. },
  156. {
  157. Name: "TestAccAggSql2",
  158. Sql: `select acc_sum(size) over (when color = "red"), color from demo`,
  159. R: [][]map[string]interface{}{
  160. {
  161. {
  162. "acc_sum": float64(3),
  163. "color": "red",
  164. },
  165. },
  166. {
  167. {
  168. "acc_sum": float64(3),
  169. "color": "blue",
  170. },
  171. },
  172. {
  173. {
  174. "acc_sum": float64(3),
  175. "color": "blue",
  176. },
  177. },
  178. {
  179. {
  180. "acc_sum": float64(3),
  181. "color": "yellow",
  182. },
  183. },
  184. {
  185. {
  186. "acc_sum": float64(4),
  187. "color": "red",
  188. },
  189. },
  190. },
  191. },
  192. {
  193. Name: "TestAccAggSql3",
  194. Sql: `select acc_min(size) over (when color = "red"), color from demo`,
  195. R: [][]map[string]interface{}{
  196. {
  197. {
  198. "acc_min": float64(3),
  199. "color": "red",
  200. },
  201. },
  202. {
  203. {
  204. "acc_min": float64(3),
  205. "color": "blue",
  206. },
  207. },
  208. {
  209. {
  210. "acc_min": float64(3),
  211. "color": "blue",
  212. },
  213. },
  214. {
  215. {
  216. "acc_min": float64(3),
  217. "color": "yellow",
  218. },
  219. },
  220. {
  221. {
  222. "acc_min": float64(1),
  223. "color": "red",
  224. },
  225. },
  226. },
  227. },
  228. {
  229. Name: "TestAccAggSql4",
  230. Sql: `select acc_max(size) over (when color = "red"), color from demo`,
  231. R: [][]map[string]interface{}{
  232. {
  233. {
  234. "acc_max": float64(3),
  235. "color": "red",
  236. },
  237. },
  238. {
  239. {
  240. "acc_max": float64(3),
  241. "color": "blue",
  242. },
  243. },
  244. {
  245. {
  246. "acc_max": float64(3),
  247. "color": "blue",
  248. },
  249. },
  250. {
  251. {
  252. "acc_max": float64(3),
  253. "color": "yellow",
  254. },
  255. },
  256. {
  257. {
  258. "acc_max": float64(3),
  259. "color": "red",
  260. },
  261. },
  262. },
  263. },
  264. {
  265. Name: "TestAccAggSql5",
  266. Sql: `select acc_count(size) over (when color = "red"), color from demo`,
  267. R: [][]map[string]interface{}{
  268. {
  269. {
  270. "acc_count": float64(1),
  271. "color": "red",
  272. },
  273. },
  274. {
  275. {
  276. "acc_count": float64(1),
  277. "color": "blue",
  278. },
  279. },
  280. {
  281. {
  282. "acc_count": float64(1),
  283. "color": "blue",
  284. },
  285. },
  286. {
  287. {
  288. "acc_count": float64(1),
  289. "color": "yellow",
  290. },
  291. },
  292. {
  293. {
  294. "acc_count": float64(2),
  295. "color": "red",
  296. },
  297. },
  298. },
  299. },
  300. {
  301. Name: "TestAccAggSql6",
  302. Sql: `select acc_avg(size) over (when color = "red"), color from demo`,
  303. R: [][]map[string]interface{}{
  304. {
  305. {
  306. "acc_avg": float64(3),
  307. "color": "red",
  308. },
  309. },
  310. {
  311. {
  312. "acc_avg": float64(3),
  313. "color": "blue",
  314. },
  315. },
  316. {
  317. {
  318. "acc_avg": float64(3),
  319. "color": "blue",
  320. },
  321. },
  322. {
  323. {
  324. "acc_avg": float64(3),
  325. "color": "yellow",
  326. },
  327. },
  328. {
  329. {
  330. "acc_avg": float64(2),
  331. "color": "red",
  332. },
  333. },
  334. },
  335. },
  336. }
  337. // Data setup
  338. HandleStream(true, streamList, t)
  339. options := []*api.RuleOption{
  340. {
  341. BufferLength: 100,
  342. SendError: true,
  343. },
  344. {
  345. BufferLength: 100,
  346. SendError: true,
  347. Qos: api.AtLeastOnce,
  348. CheckpointInterval: 5000,
  349. },
  350. {
  351. BufferLength: 100,
  352. SendError: true,
  353. Qos: api.ExactlyOnce,
  354. CheckpointInterval: 5000,
  355. },
  356. }
  357. for j, opt := range options {
  358. DoRuleTest(t, tests, j, opt, 0)
  359. }
  360. }
  361. func TestLimitSQL(t *testing.T) {
  362. // Reset
  363. streamList := []string{"demo", "demoArr", "demoArr2"}
  364. HandleStream(false, streamList, t)
  365. var r [][]map[string]interface{}
  366. tests := []RuleTest{
  367. {
  368. Name: "TestLimitSQL01",
  369. Sql: `SELECT unnest(demoArr2.arr) as col, demo.size FROM demo inner join demoArr2 on demo.size = demoArr2.x group by SESSIONWINDOW(ss, 2, 1) limit 1;`,
  370. R: [][]map[string]interface{}{
  371. {
  372. {
  373. "col": float64(1),
  374. "size": float64(1),
  375. },
  376. },
  377. },
  378. },
  379. {
  380. Name: "TestLimitSQL0",
  381. Sql: `SELECT unnest(demoArr.arr3) as col, demo.size FROM demo inner join demoArr on demo.size = demoArr.x group by SESSIONWINDOW(ss, 2, 1) limit 1;`,
  382. R: [][]map[string]interface{}{
  383. {
  384. {
  385. "col": float64(1),
  386. "size": float64(1),
  387. },
  388. },
  389. },
  390. },
  391. {
  392. Name: "TestLimitSQL1",
  393. Sql: `SELECT unnest(demoArr.arr3) as col, demo.size FROM demo inner join demoArr on demo.size = demoArr.x group by SESSIONWINDOW(ss, 2, 1) limit 0;`,
  394. R: r,
  395. },
  396. {
  397. Name: "TestLimitSQL2",
  398. Sql: `SELECT demo.size FROM demo inner join demoArr on demo.size = demoArr.x group by SESSIONWINDOW(ss, 2, 1) limit 1;`,
  399. R: [][]map[string]interface{}{
  400. {
  401. {
  402. "size": float64(1),
  403. },
  404. },
  405. },
  406. },
  407. {
  408. Name: "TestLimitSQL3",
  409. Sql: `SELECT demo.size FROM demo inner join demoArr on demo.size = demoArr.x group by SESSIONWINDOW(ss, 2, 1) limit 0;`,
  410. R: r,
  411. },
  412. }
  413. // Data setup
  414. HandleStream(true, streamList, t)
  415. options := []*api.RuleOption{
  416. {
  417. BufferLength: 100,
  418. SendError: true,
  419. },
  420. {
  421. BufferLength: 100,
  422. SendError: true,
  423. Debug: true,
  424. LogFilename: "rule-test.log",
  425. },
  426. {
  427. BufferLength: 100,
  428. SendError: true,
  429. Qos: api.AtLeastOnce,
  430. CheckpointInterval: 5000,
  431. },
  432. {
  433. BufferLength: 100,
  434. SendError: true,
  435. Qos: api.ExactlyOnce,
  436. CheckpointInterval: 5000,
  437. },
  438. }
  439. for j, opt := range options {
  440. DoRuleTest(t, tests, j, opt, 0)
  441. }
  442. }
  443. func TestSRFSQL(t *testing.T) {
  444. // Reset
  445. streamList := []string{"demo", "demoArr"}
  446. HandleStream(false, streamList, t)
  447. tests := []RuleTest{
  448. {
  449. Name: "TestSingleSQLRule25",
  450. Sql: "SELECT unnest(a) from demoArr group by SESSIONWINDOW(ss, 2, 1);",
  451. R: [][]map[string]interface{}{
  452. {
  453. {
  454. "error": "the argument for the unnest function should be array",
  455. },
  456. },
  457. },
  458. },
  459. {
  460. Name: "TestSingleSQLRule24",
  461. Sql: "Select unnest(a) from demoArr;",
  462. R: [][]map[string]interface{}{
  463. {
  464. {
  465. "error": "the argument for the unnest function should be array",
  466. },
  467. },
  468. },
  469. },
  470. {
  471. Name: "TestSingleSQLRule21",
  472. Sql: `SELECT unnest(demoArr.arr3) as col, demo.size FROM demo inner join demoArr on demo.size = demoArr.x group by SESSIONWINDOW(ss, 2, 1);`,
  473. R: [][]map[string]interface{}{
  474. {
  475. {
  476. "col": float64(1),
  477. "size": float64(1),
  478. },
  479. {
  480. "col": float64(2),
  481. "size": float64(1),
  482. },
  483. {
  484. "col": float64(3),
  485. "size": float64(1),
  486. },
  487. },
  488. },
  489. },
  490. {
  491. Name: "TestSingleSQLRule22",
  492. Sql: `SELECT unnest(arr3) as col,y From demoArr group by y, SESSIONWINDOW(ss, 2, 1);`,
  493. R: [][]map[string]interface{}{
  494. {
  495. {
  496. "col": float64(1),
  497. "y": float64(2),
  498. },
  499. {
  500. "col": float64(2),
  501. "y": float64(2),
  502. },
  503. {
  504. "col": float64(3),
  505. "y": float64(2),
  506. },
  507. },
  508. },
  509. },
  510. {
  511. Name: "TestSingleSQLRule23",
  512. Sql: "SELECT unnest(arr3) as col,a from demoArr group by SESSIONWINDOW(ss, 2, 1);",
  513. R: [][]map[string]interface{}{
  514. {
  515. {
  516. "col": float64(1),
  517. "a": float64(6),
  518. },
  519. {
  520. "col": float64(2),
  521. "a": float64(6),
  522. },
  523. {
  524. "col": float64(3),
  525. "a": float64(6),
  526. },
  527. },
  528. },
  529. },
  530. {
  531. Name: `TestSingleSQLRule18`,
  532. Sql: `SELECT unnest(arr2) FROM demoArr where x=1`,
  533. R: [][]map[string]interface{}{
  534. {
  535. {
  536. "a": float64(1),
  537. "b": float64(2),
  538. },
  539. },
  540. {
  541. {
  542. "a": float64(3),
  543. "b": float64(4),
  544. },
  545. },
  546. },
  547. },
  548. // The mapping schema created by unnest function will cover the original column if they have the same column name
  549. {
  550. Name: `TestSingleSQLRule19`,
  551. Sql: `SELECT unnest(arr2),a FROM demoArr where x=1`,
  552. R: [][]map[string]interface{}{
  553. {
  554. {
  555. "a": float64(1),
  556. "b": float64(2),
  557. },
  558. },
  559. {
  560. {
  561. "a": float64(3),
  562. "b": float64(4),
  563. },
  564. },
  565. },
  566. },
  567. {
  568. Name: `TestSingleSQLRule20`,
  569. Sql: `SELECT unnest(arr3) as col FROM demoArr where x=1`,
  570. R: [][]map[string]interface{}{
  571. {
  572. {
  573. "col": float64(1),
  574. },
  575. },
  576. {
  577. {
  578. "col": float64(2),
  579. },
  580. },
  581. {
  582. {
  583. "col": float64(3),
  584. },
  585. },
  586. },
  587. },
  588. {
  589. Name: `TestSingleSQLRule21`,
  590. Sql: `SELECT unnest(arr2),x FROM demoArr where x=1`,
  591. R: [][]map[string]interface{}{
  592. {
  593. {
  594. "a": float64(1),
  595. "b": float64(2),
  596. "x": float64(1),
  597. },
  598. },
  599. {
  600. {
  601. "a": float64(3),
  602. "b": float64(4),
  603. "x": float64(1),
  604. },
  605. },
  606. },
  607. },
  608. }
  609. // Data setup
  610. HandleStream(true, streamList, t)
  611. options := []*api.RuleOption{
  612. {
  613. BufferLength: 100,
  614. SendError: true,
  615. }, {
  616. BufferLength: 100,
  617. SendError: true,
  618. Qos: api.AtLeastOnce,
  619. CheckpointInterval: 5000,
  620. }, {
  621. BufferLength: 100,
  622. SendError: true,
  623. Qos: api.ExactlyOnce,
  624. CheckpointInterval: 5000,
  625. },
  626. }
  627. for j, opt := range options {
  628. DoRuleTest(t, tests, j, opt, 0)
  629. }
  630. }
  631. func TestSingleSQL(t *testing.T) {
  632. // Reset
  633. streamList := []string{"demo", "demoError", "demo1", "table1", "demoTable", "demoArr"}
  634. HandleStream(false, streamList, t)
  635. // Data setup
  636. tests := []RuleTest{
  637. {
  638. Name: `TestAnalyzeFuncAlias1`,
  639. Sql: `SELECT lag(size,1,0) + 1 as b, lag(b,1,0),size FROM demo Group by COUNTWINDOW(5)`,
  640. R: [][]map[string]interface{}{
  641. {
  642. {
  643. "b": float64(1),
  644. "lag": float64(0),
  645. "size": float64(3),
  646. },
  647. {
  648. "b": float64(4),
  649. "lag": float64(1),
  650. "size": float64(6),
  651. },
  652. {
  653. "b": float64(7),
  654. "lag": float64(4),
  655. "size": float64(2),
  656. },
  657. {
  658. "b": float64(3),
  659. "lag": float64(7),
  660. "size": float64(4),
  661. },
  662. {
  663. "b": float64(5),
  664. "lag": float64(3),
  665. "size": float64(1),
  666. },
  667. },
  668. },
  669. },
  670. {
  671. Name: `TestAnalyzeFuncAlias2`,
  672. Sql: `SELECT lag(size,1,0) + 1 as b, lag(b,1,0),size FROM demo`,
  673. R: [][]map[string]interface{}{
  674. {
  675. {
  676. "b": float64(1),
  677. "lag": float64(0),
  678. "size": float64(3),
  679. },
  680. },
  681. {
  682. {
  683. "b": float64(4),
  684. "lag": float64(1),
  685. "size": float64(6),
  686. },
  687. },
  688. {
  689. {
  690. "b": float64(7),
  691. "lag": float64(4),
  692. "size": float64(2),
  693. },
  694. },
  695. {
  696. {
  697. "b": float64(3),
  698. "lag": float64(7),
  699. "size": float64(4),
  700. },
  701. },
  702. {
  703. {
  704. "b": float64(5),
  705. "lag": float64(3),
  706. "size": float64(1),
  707. },
  708. },
  709. },
  710. },
  711. {
  712. Name: `TestSingleSQLRule0`,
  713. Sql: `SELECT arr[x:y+1] as col1 FROM demoArr where x=1`,
  714. R: [][]map[string]interface{}{
  715. {{
  716. "col1": []interface{}{
  717. float64(2), float64(3),
  718. },
  719. }},
  720. },
  721. },
  722. {
  723. Name: `TestSingleSQLRule1`,
  724. Sql: `SELECT *, upper(color), event_time() FROM demo`,
  725. R: [][]map[string]interface{}{
  726. {{
  727. "color": "red",
  728. "size": float64(3),
  729. "ts": float64(1541152486013),
  730. "upper": "RED",
  731. "event_time": float64(1541152486013),
  732. }},
  733. {{
  734. "color": "blue",
  735. "size": float64(6),
  736. "ts": float64(1541152486822),
  737. "upper": "BLUE",
  738. "event_time": float64(1541152486822),
  739. }},
  740. {{
  741. "color": "blue",
  742. "size": float64(2),
  743. "ts": float64(1541152487632),
  744. "upper": "BLUE",
  745. "event_time": float64(1541152487632),
  746. }},
  747. {{
  748. "color": "yellow",
  749. "size": float64(4),
  750. "ts": float64(1541152488442),
  751. "upper": "YELLOW",
  752. "event_time": float64(1541152488442),
  753. }},
  754. {{
  755. "color": "red",
  756. "size": float64(1),
  757. "ts": float64(1541152489252),
  758. "upper": "RED",
  759. "event_time": float64(1541152489252),
  760. }},
  761. },
  762. M: map[string]interface{}{
  763. "op_2_project_0_exceptions_total": int64(0),
  764. "op_2_project_0_process_latency_us": int64(0),
  765. "op_2_project_0_records_in_total": int64(5),
  766. "op_2_project_0_records_out_total": int64(5),
  767. "sink_mockSink_0_exceptions_total": int64(0),
  768. "sink_mockSink_0_records_in_total": int64(5),
  769. "sink_mockSink_0_records_out_total": int64(5),
  770. "source_demo_0_exceptions_total": int64(0),
  771. "source_demo_0_records_in_total": int64(5),
  772. "source_demo_0_records_out_total": int64(5),
  773. },
  774. T: &api.PrintableTopo{
  775. Sources: []string{"source_demo"},
  776. Edges: map[string][]interface{}{
  777. "source_demo": {"op_2_project"},
  778. "op_2_project": {"sink_mockSink"},
  779. },
  780. },
  781. },
  782. {
  783. Name: `TestSingleSQLRule2`,
  784. Sql: `SELECT color, ts, last_hit_count() + 1 as lc FROM demo where size > 3`,
  785. R: [][]map[string]interface{}{
  786. {{
  787. "color": "blue",
  788. "ts": float64(1541152486822),
  789. "lc": float64(1),
  790. }},
  791. {{
  792. "color": "yellow",
  793. "ts": float64(1541152488442),
  794. "lc": float64(2),
  795. }},
  796. },
  797. M: map[string]interface{}{
  798. "op_3_project_0_exceptions_total": int64(0),
  799. "op_3_project_0_process_latency_us": int64(0),
  800. "op_3_project_0_records_in_total": int64(2),
  801. "op_3_project_0_records_out_total": int64(2),
  802. "sink_mockSink_0_exceptions_total": int64(0),
  803. "sink_mockSink_0_records_in_total": int64(2),
  804. "sink_mockSink_0_records_out_total": int64(2),
  805. "source_demo_0_exceptions_total": int64(0),
  806. "source_demo_0_records_in_total": int64(5),
  807. "source_demo_0_records_out_total": int64(5),
  808. "op_2_filter_0_exceptions_total": int64(0),
  809. "op_2_filter_0_process_latency_us": int64(0),
  810. "op_2_filter_0_records_in_total": int64(5),
  811. "op_2_filter_0_records_out_total": int64(2),
  812. },
  813. },
  814. {
  815. Name: `TestSingleSQLRule3`,
  816. Sql: `SELECT size as Int8, ts FROM demo where size > 3`,
  817. R: [][]map[string]interface{}{
  818. {{
  819. "Int8": float64(6),
  820. "ts": float64(1541152486822),
  821. }},
  822. {{
  823. "Int8": float64(4),
  824. "ts": float64(1541152488442),
  825. }},
  826. },
  827. M: map[string]interface{}{
  828. "op_3_project_0_exceptions_total": int64(0),
  829. "op_3_project_0_process_latency_us": int64(0),
  830. "op_3_project_0_records_in_total": int64(2),
  831. "op_3_project_0_records_out_total": int64(2),
  832. "sink_mockSink_0_exceptions_total": int64(0),
  833. "sink_mockSink_0_records_in_total": int64(2),
  834. "sink_mockSink_0_records_out_total": int64(2),
  835. "source_demo_0_exceptions_total": int64(0),
  836. "source_demo_0_records_in_total": int64(5),
  837. "source_demo_0_records_out_total": int64(5),
  838. "op_2_filter_0_exceptions_total": int64(0),
  839. "op_2_filter_0_process_latency_us": int64(0),
  840. "op_2_filter_0_records_in_total": int64(5),
  841. "op_2_filter_0_records_out_total": int64(2),
  842. },
  843. },
  844. {
  845. Name: `TestSingleSQLRule4`,
  846. Sql: `SELECT size as Int8, ts FROM demoError where size > 3`,
  847. R: [][]map[string]interface{}{
  848. {{
  849. "error": "error in preprocessor: field size type mismatch: cannot convert string(red) to int64",
  850. }},
  851. {{
  852. "Int8": float64(6),
  853. "ts": float64(1541152486822),
  854. }},
  855. {{
  856. "Int8": float64(4),
  857. "ts": float64(1541152488442),
  858. }},
  859. {{
  860. "error": "error in preprocessor: field size type mismatch: cannot convert string(blue) to int64",
  861. }},
  862. },
  863. M: map[string]interface{}{
  864. "op_3_project_0_exceptions_total": int64(2),
  865. "op_3_project_0_process_latency_us": int64(0),
  866. "op_3_project_0_records_in_total": int64(2),
  867. "op_3_project_0_records_out_total": int64(2),
  868. "sink_mockSink_0_exceptions_total": int64(0),
  869. "sink_mockSink_0_records_in_total": int64(4),
  870. "sink_mockSink_0_records_out_total": int64(4),
  871. "source_demoError_0_exceptions_total": int64(2),
  872. "source_demoError_0_records_in_total": int64(5),
  873. "source_demoError_0_records_out_total": int64(3),
  874. "op_2_filter_0_exceptions_total": int64(2),
  875. "op_2_filter_0_process_latency_us": int64(0),
  876. "op_2_filter_0_records_in_total": int64(3),
  877. "op_2_filter_0_records_out_total": int64(2),
  878. },
  879. },
  880. {
  881. Name: `TestSingleSQLRule5`,
  882. Sql: `SELECT meta(topic) as m, ts FROM demo WHERE last_hit_count() < 4`,
  883. R: [][]map[string]interface{}{
  884. {{
  885. "m": "mock",
  886. "ts": float64(1541152486013),
  887. }},
  888. {{
  889. "m": "mock",
  890. "ts": float64(1541152486822),
  891. }},
  892. {{
  893. "m": "mock",
  894. "ts": float64(1541152487632),
  895. }},
  896. {{
  897. "m": "mock",
  898. "ts": float64(1541152488442),
  899. }},
  900. },
  901. M: map[string]interface{}{
  902. "sink_mockSink_0_exceptions_total": int64(0),
  903. "sink_mockSink_0_records_in_total": int64(4),
  904. "sink_mockSink_0_records_out_total": int64(4),
  905. "source_demo_0_exceptions_total": int64(0),
  906. "source_demo_0_records_in_total": int64(5),
  907. "source_demo_0_records_out_total": int64(5),
  908. },
  909. },
  910. {
  911. Name: `TestSingleSQLRule6`,
  912. Sql: `SELECT color, ts FROM demo where size > 3 and meta(topic)="mock"`,
  913. R: [][]map[string]interface{}{
  914. {{
  915. "color": "blue",
  916. "ts": float64(1541152486822),
  917. }},
  918. {{
  919. "color": "yellow",
  920. "ts": float64(1541152488442),
  921. }},
  922. },
  923. M: map[string]interface{}{
  924. "op_3_project_0_exceptions_total": int64(0),
  925. "op_3_project_0_process_latency_us": int64(0),
  926. "op_3_project_0_records_in_total": int64(2),
  927. "op_3_project_0_records_out_total": int64(2),
  928. "sink_mockSink_0_exceptions_total": int64(0),
  929. "sink_mockSink_0_records_in_total": int64(2),
  930. "sink_mockSink_0_records_out_total": int64(2),
  931. "source_demo_0_exceptions_total": int64(0),
  932. "source_demo_0_records_in_total": int64(5),
  933. "source_demo_0_records_out_total": int64(5),
  934. "op_2_filter_0_exceptions_total": int64(0),
  935. "op_2_filter_0_process_latency_us": int64(0),
  936. "op_2_filter_0_records_in_total": int64(5),
  937. "op_2_filter_0_records_out_total": int64(2),
  938. },
  939. },
  940. {
  941. Name: `TestSingleSQLRule7`,
  942. Sql: "SELECT `from` FROM demo1",
  943. R: [][]map[string]interface{}{
  944. {{
  945. "from": "device1",
  946. }},
  947. {{
  948. "from": "device2",
  949. }},
  950. {{
  951. "from": "device3",
  952. }},
  953. {{
  954. "from": "device1",
  955. }},
  956. {{
  957. "from": "device3",
  958. }},
  959. },
  960. M: map[string]interface{}{
  961. "op_2_project_0_exceptions_total": int64(0),
  962. "op_2_project_0_process_latency_us": int64(0),
  963. "op_2_project_0_records_in_total": int64(5),
  964. "op_2_project_0_records_out_total": int64(5),
  965. "sink_mockSink_0_exceptions_total": int64(0),
  966. "sink_mockSink_0_records_in_total": int64(5),
  967. "sink_mockSink_0_records_out_total": int64(5),
  968. "source_demo1_0_exceptions_total": int64(0),
  969. "source_demo1_0_records_in_total": int64(5),
  970. "source_demo1_0_records_out_total": int64(5),
  971. },
  972. },
  973. {
  974. Name: `TestSingleSQLRule8`,
  975. Sql: "SELECT * FROM demo1 where `from`=\"device1\"",
  976. R: [][]map[string]interface{}{
  977. {{
  978. "temp": float64(25.5),
  979. "hum": float64(65),
  980. "from": "device1",
  981. "ts": float64(1541152486013),
  982. }},
  983. {{
  984. "temp": float64(27.4),
  985. "hum": float64(80),
  986. "from": "device1",
  987. "ts": float64(1541152488442),
  988. }},
  989. },
  990. M: map[string]interface{}{
  991. "op_3_project_0_exceptions_total": int64(0),
  992. "op_3_project_0_process_latency_us": int64(0),
  993. "op_3_project_0_records_in_total": int64(2),
  994. "op_3_project_0_records_out_total": int64(2),
  995. "op_2_filter_0_exceptions_total": int64(0),
  996. "op_2_filter_0_process_latency_us": int64(0),
  997. "op_2_filter_0_records_in_total": int64(5),
  998. "op_2_filter_0_records_out_total": int64(2),
  999. "sink_mockSink_0_exceptions_total": int64(0),
  1000. "sink_mockSink_0_records_in_total": int64(2),
  1001. "sink_mockSink_0_records_out_total": int64(2),
  1002. "source_demo1_0_exceptions_total": int64(0),
  1003. "source_demo1_0_records_in_total": int64(5),
  1004. "source_demo1_0_records_out_total": int64(5),
  1005. },
  1006. },
  1007. {
  1008. Name: `TestSingleSQLRule9`,
  1009. Sql: `SELECT color, CASE WHEN size < 2 THEN "S" WHEN size < 4 THEN "M" ELSE "L" END as s, ts FROM demo`,
  1010. R: [][]map[string]interface{}{
  1011. {{
  1012. "color": "red",
  1013. "s": "M",
  1014. "ts": float64(1541152486013),
  1015. }},
  1016. {{
  1017. "color": "blue",
  1018. "s": "L",
  1019. "ts": float64(1541152486822),
  1020. }},
  1021. {{
  1022. "color": "blue",
  1023. "s": "M",
  1024. "ts": float64(1541152487632),
  1025. }},
  1026. {{
  1027. "color": "yellow",
  1028. "s": "L",
  1029. "ts": float64(1541152488442),
  1030. }},
  1031. {{
  1032. "color": "red",
  1033. "s": "S",
  1034. "ts": float64(1541152489252),
  1035. }},
  1036. },
  1037. M: map[string]interface{}{
  1038. "op_2_project_0_exceptions_total": int64(0),
  1039. "op_2_project_0_process_latency_us": int64(0),
  1040. "op_2_project_0_records_in_total": int64(5),
  1041. "op_2_project_0_records_out_total": int64(5),
  1042. "sink_mockSink_0_exceptions_total": int64(0),
  1043. "sink_mockSink_0_records_in_total": int64(5),
  1044. "sink_mockSink_0_records_out_total": int64(5),
  1045. "source_demo_0_exceptions_total": int64(0),
  1046. "source_demo_0_records_in_total": int64(5),
  1047. "source_demo_0_records_out_total": int64(5),
  1048. },
  1049. T: &api.PrintableTopo{
  1050. Sources: []string{"source_demo"},
  1051. Edges: map[string][]interface{}{
  1052. "source_demo": {"op_2_project"},
  1053. "op_2_project": {"sink_mockSink"},
  1054. },
  1055. },
  1056. },
  1057. {
  1058. Name: `TestSingleSQLRule10`,
  1059. Sql: "SELECT * FROM demo INNER JOIN table1 on demo.ts = table1.id",
  1060. R: [][]map[string]interface{}{
  1061. {{
  1062. "id": float64(1541152486013),
  1063. "name": "name1",
  1064. "color": "red",
  1065. "size": float64(3),
  1066. "ts": float64(1541152486013),
  1067. }},
  1068. {{
  1069. "id": float64(1541152487632),
  1070. "name": "name2",
  1071. "color": "blue",
  1072. "size": float64(2),
  1073. "ts": float64(1541152487632),
  1074. }},
  1075. {{
  1076. "id": float64(1541152489252),
  1077. "name": "name3",
  1078. "color": "red",
  1079. "size": float64(1),
  1080. "ts": float64(1541152489252),
  1081. }},
  1082. },
  1083. W: 15,
  1084. M: map[string]interface{}{
  1085. "op_3_join_aligner_0_records_in_total": int64(6),
  1086. "op_3_join_aligner_0_records_out_total": int64(5),
  1087. "op_4_join_0_exceptions_total": int64(0),
  1088. "op_4_join_0_records_in_total": int64(5),
  1089. "op_4_join_0_records_out_total": int64(3),
  1090. "op_5_project_0_exceptions_total": int64(0),
  1091. "op_5_project_0_records_in_total": int64(3),
  1092. "op_5_project_0_records_out_total": int64(3),
  1093. "sink_mockSink_0_exceptions_total": int64(0),
  1094. "sink_mockSink_0_records_in_total": int64(3),
  1095. "sink_mockSink_0_records_out_total": int64(3),
  1096. "source_demo_0_exceptions_total": int64(0),
  1097. "source_demo_0_records_in_total": int64(5),
  1098. "source_demo_0_records_out_total": int64(5),
  1099. "source_table1_0_exceptions_total": int64(0),
  1100. "source_table1_0_records_in_total": int64(4),
  1101. "source_table1_0_records_out_total": int64(1),
  1102. },
  1103. },
  1104. {
  1105. Name: `TestSingleSQLRule11`,
  1106. Sql: "SELECT device FROM demo INNER JOIN demoTable on demo.ts = demoTable.ts",
  1107. R: [][]map[string]interface{}{
  1108. {{
  1109. "device": "device2",
  1110. }},
  1111. {{
  1112. "device": "device4",
  1113. }},
  1114. {{
  1115. "device": "device5",
  1116. }},
  1117. },
  1118. M: map[string]interface{}{
  1119. "op_3_join_aligner_0_records_in_total": int64(10),
  1120. "op_3_join_aligner_0_records_out_total": int64(5),
  1121. "op_4_join_0_exceptions_total": int64(0),
  1122. "op_4_join_0_records_in_total": int64(5),
  1123. "op_4_join_0_records_out_total": int64(3),
  1124. "op_5_project_0_exceptions_total": int64(0),
  1125. "op_5_project_0_records_in_total": int64(3),
  1126. "op_5_project_0_records_out_total": int64(3),
  1127. "sink_mockSink_0_exceptions_total": int64(0),
  1128. "sink_mockSink_0_records_in_total": int64(3),
  1129. "sink_mockSink_0_records_out_total": int64(3),
  1130. "source_demo_0_exceptions_total": int64(0),
  1131. "source_demo_0_records_in_total": int64(5),
  1132. "source_demo_0_records_out_total": int64(5),
  1133. "source_demoTable_0_exceptions_total": int64(0),
  1134. "source_demoTable_0_records_in_total": int64(5),
  1135. "source_demoTable_0_records_out_total": int64(5),
  1136. },
  1137. },
  1138. {
  1139. Name: `TestSingleSQLRule12`,
  1140. Sql: "SELECT demo.ts as demoTs, table1.id as table1Id FROM demo INNER JOIN table1 on demoTs = table1Id",
  1141. R: [][]map[string]interface{}{
  1142. {{
  1143. "table1Id": float64(1541152486013),
  1144. "demoTs": float64(1541152486013),
  1145. }},
  1146. {{
  1147. "table1Id": float64(1541152487632),
  1148. "demoTs": float64(1541152487632),
  1149. }},
  1150. {{
  1151. "table1Id": float64(1541152489252),
  1152. "demoTs": float64(1541152489252),
  1153. }},
  1154. },
  1155. W: 15,
  1156. M: map[string]interface{}{
  1157. "op_3_join_aligner_0_records_in_total": int64(6),
  1158. "op_3_join_aligner_0_records_out_total": int64(5),
  1159. "op_4_join_0_exceptions_total": int64(0),
  1160. "op_4_join_0_records_in_total": int64(5),
  1161. "op_4_join_0_records_out_total": int64(3),
  1162. "op_5_project_0_exceptions_total": int64(0),
  1163. "op_5_project_0_records_in_total": int64(3),
  1164. "op_5_project_0_records_out_total": int64(3),
  1165. "sink_mockSink_0_exceptions_total": int64(0),
  1166. "sink_mockSink_0_records_in_total": int64(3),
  1167. "sink_mockSink_0_records_out_total": int64(3),
  1168. "source_demo_0_exceptions_total": int64(0),
  1169. "source_demo_0_records_in_total": int64(5),
  1170. "source_demo_0_records_out_total": int64(5),
  1171. "source_table1_0_exceptions_total": int64(0),
  1172. "source_table1_0_records_in_total": int64(4),
  1173. "source_table1_0_records_out_total": int64(1),
  1174. },
  1175. },
  1176. {
  1177. Name: `TestChanged13`,
  1178. Sql: "SELECT changed_cols(\"tt_\", true, color, size) FROM demo",
  1179. R: [][]map[string]interface{}{
  1180. {{
  1181. "tt_color": "red",
  1182. "tt_size": float64(3),
  1183. }},
  1184. {{
  1185. "tt_color": "blue",
  1186. "tt_size": float64(6),
  1187. }},
  1188. {{
  1189. "tt_size": float64(2),
  1190. }},
  1191. {{
  1192. "tt_color": "yellow",
  1193. "tt_size": float64(4),
  1194. }},
  1195. {{
  1196. "tt_color": "red",
  1197. "tt_size": float64(1),
  1198. }},
  1199. },
  1200. M: map[string]interface{}{
  1201. "op_2_project_0_exceptions_total": int64(0),
  1202. "op_2_project_0_process_latency_us": int64(0),
  1203. "op_2_project_0_records_in_total": int64(5),
  1204. "op_2_project_0_records_out_total": int64(5),
  1205. "sink_mockSink_0_exceptions_total": int64(0),
  1206. "sink_mockSink_0_records_in_total": int64(5),
  1207. "sink_mockSink_0_records_out_total": int64(5),
  1208. "source_demo_0_exceptions_total": int64(0),
  1209. "source_demo_0_records_in_total": int64(5),
  1210. "source_demo_0_records_out_total": int64(5),
  1211. },
  1212. },
  1213. {
  1214. Name: `TestAliasOrderBy14`,
  1215. Sql: "SELECT color, count(*) as c FROM demo where color != \"red\" GROUP BY COUNTWINDOW(5), color Order by c DESC",
  1216. R: [][]map[string]interface{}{
  1217. {
  1218. {
  1219. "color": "blue",
  1220. "c": float64(2),
  1221. },
  1222. {
  1223. "color": "yellow",
  1224. "c": float64(1),
  1225. },
  1226. },
  1227. },
  1228. M: map[string]interface{}{
  1229. "op_6_project_0_exceptions_total": int64(0),
  1230. "op_6_project_0_process_latency_us": int64(0),
  1231. "op_6_project_0_records_in_total": int64(1),
  1232. "op_6_project_0_records_out_total": int64(1),
  1233. "sink_mockSink_0_exceptions_total": int64(0),
  1234. "sink_mockSink_0_records_in_total": int64(1),
  1235. "sink_mockSink_0_records_out_total": int64(1),
  1236. "source_demo_0_exceptions_total": int64(0),
  1237. "source_demo_0_records_in_total": int64(5),
  1238. "source_demo_0_records_out_total": int64(5),
  1239. },
  1240. },
  1241. {
  1242. Name: `TestSingleSQLRule17`,
  1243. Sql: `SELECT arr[x:4] as col1 FROM demoArr where x=1`,
  1244. R: [][]map[string]interface{}{
  1245. {{
  1246. "col1": []interface{}{
  1247. float64(2), float64(3), float64(4),
  1248. },
  1249. }},
  1250. },
  1251. },
  1252. {
  1253. Name: `TestSingleSQLRule16`,
  1254. Sql: `SELECT arr[1:y] as col1 FROM demoArr where x=1`,
  1255. R: [][]map[string]interface{}{
  1256. {{
  1257. "col1": []interface{}{
  1258. float64(2),
  1259. },
  1260. }},
  1261. },
  1262. },
  1263. {
  1264. Name: `TestSingleSQLRule15`,
  1265. Sql: `SELECT arr[1] as col1 FROM demoArr where x=1`,
  1266. R: [][]map[string]interface{}{
  1267. {{
  1268. "col1": float64(2),
  1269. }},
  1270. },
  1271. },
  1272. {
  1273. Name: `TestLagAlias`,
  1274. Sql: "SELECT lag(size) as lastSize, lag(had_changed(true,size)), size, lastSize/size as changeRate FROM demo WHERE size > 2",
  1275. R: [][]map[string]interface{}{
  1276. {{
  1277. "size": float64(3),
  1278. }},
  1279. {{
  1280. "lastSize": float64(3),
  1281. "size": float64(6),
  1282. "lag": true,
  1283. "changeRate": float64(0),
  1284. }},
  1285. {{
  1286. "lastSize": float64(2),
  1287. "size": float64(4),
  1288. "lag": true,
  1289. "changeRate": float64(0),
  1290. }},
  1291. },
  1292. M: map[string]interface{}{
  1293. "sink_mockSink_0_exceptions_total": int64(0),
  1294. "sink_mockSink_0_records_in_total": int64(3),
  1295. "sink_mockSink_0_records_out_total": int64(3),
  1296. "source_demo_0_exceptions_total": int64(0),
  1297. "source_demo_0_records_in_total": int64(5),
  1298. "source_demo_0_records_out_total": int64(5),
  1299. },
  1300. },
  1301. {
  1302. Name: `TestLagPartition`,
  1303. Sql: "SELECT color, lag(size) over (partition by color) as lastSize, size, lastSize/size as changeRate FROM demo",
  1304. R: [][]map[string]interface{}{
  1305. {{
  1306. "color": "red",
  1307. "size": float64(3),
  1308. }},
  1309. {{
  1310. "color": "blue",
  1311. "size": float64(6),
  1312. }},
  1313. {{
  1314. "color": "blue",
  1315. "lastSize": float64(6),
  1316. "size": float64(2),
  1317. "changeRate": float64(3),
  1318. }},
  1319. {{
  1320. "color": "yellow",
  1321. "size": float64(4),
  1322. }},
  1323. {{
  1324. "color": "red",
  1325. "lastSize": float64(3),
  1326. "size": float64(1),
  1327. "changeRate": float64(3),
  1328. }},
  1329. },
  1330. M: map[string]interface{}{
  1331. "sink_mockSink_0_exceptions_total": int64(0),
  1332. "sink_mockSink_0_records_in_total": int64(5),
  1333. "sink_mockSink_0_records_out_total": int64(5),
  1334. "source_demo_0_exceptions_total": int64(0),
  1335. "source_demo_0_records_in_total": int64(5),
  1336. "source_demo_0_records_out_total": int64(5),
  1337. },
  1338. },
  1339. }
  1340. HandleStream(true, streamList, t)
  1341. options := []*api.RuleOption{
  1342. {
  1343. BufferLength: 100,
  1344. SendError: true,
  1345. },
  1346. {
  1347. BufferLength: 100,
  1348. SendError: true,
  1349. Qos: api.AtLeastOnce,
  1350. CheckpointInterval: 5000,
  1351. },
  1352. {
  1353. BufferLength: 100,
  1354. SendError: true,
  1355. Qos: api.ExactlyOnce,
  1356. CheckpointInterval: 5000,
  1357. },
  1358. }
  1359. for j, opt := range options {
  1360. DoRuleTest(t, tests, j, opt, 0)
  1361. }
  1362. }
  1363. func TestSingleSQLWithEventTime(t *testing.T) {
  1364. // Reset
  1365. streamList := []string{"demoE"}
  1366. HandleStream(false, streamList, t)
  1367. // Data setup
  1368. tests := []RuleTest{
  1369. {
  1370. Name: `TestSingleSQLRule1`,
  1371. Sql: `SELECT *, upper(color) FROM demoE`,
  1372. R: [][]map[string]interface{}{
  1373. {{
  1374. "color": "red",
  1375. "size": float64(3),
  1376. "ts": float64(1541152486013),
  1377. "upper": "RED",
  1378. }},
  1379. {{
  1380. "color": "blue",
  1381. "size": float64(2),
  1382. "ts": float64(1541152487632),
  1383. "upper": "BLUE",
  1384. }},
  1385. {{
  1386. "color": "yellow",
  1387. "size": float64(4),
  1388. "ts": float64(1541152488442),
  1389. "upper": "YELLOW",
  1390. }},
  1391. {{
  1392. "color": "red",
  1393. "size": float64(1),
  1394. "ts": float64(1541152489252),
  1395. "upper": "RED",
  1396. }},
  1397. },
  1398. M: map[string]interface{}{
  1399. "op_3_project_0_exceptions_total": int64(0),
  1400. "op_3_project_0_process_latency_us": int64(0),
  1401. "op_3_project_0_records_in_total": int64(4),
  1402. "op_3_project_0_records_out_total": int64(4),
  1403. "sink_mockSink_0_exceptions_total": int64(0),
  1404. "sink_mockSink_0_records_in_total": int64(4),
  1405. "sink_mockSink_0_records_out_total": int64(4),
  1406. "source_demoE_0_exceptions_total": int64(0),
  1407. "source_demoE_0_records_in_total": int64(6),
  1408. "source_demoE_0_records_out_total": int64(6),
  1409. },
  1410. T: &api.PrintableTopo{
  1411. Sources: []string{"source_demoE"},
  1412. Edges: map[string][]interface{}{
  1413. "source_demoE": {"op_2_watermark"},
  1414. "op_2_watermark": {"op_3_project"},
  1415. "op_3_project": {"sink_mockSink"},
  1416. },
  1417. },
  1418. },
  1419. {
  1420. Name: `TestStateFunc`,
  1421. Sql: `SELECT *, last_hit_time() as lt, last_hit_count() as lc, event_time() as et FROM demoE WHERE size < 3 AND lc < 2`,
  1422. R: [][]map[string]interface{}{
  1423. {{
  1424. "color": "blue",
  1425. "size": float64(2),
  1426. "ts": float64(1541152487632),
  1427. "lc": float64(0),
  1428. "lt": float64(0),
  1429. "et": float64(1541152487632),
  1430. }},
  1431. {{
  1432. "color": "red",
  1433. "size": float64(1),
  1434. "ts": float64(1541152489252),
  1435. "lc": float64(1),
  1436. "lt": float64(1541152487632),
  1437. "et": float64(1541152489252),
  1438. }},
  1439. },
  1440. M: map[string]interface{}{
  1441. "sink_mockSink_0_exceptions_total": int64(0),
  1442. "sink_mockSink_0_records_in_total": int64(2),
  1443. "sink_mockSink_0_records_out_total": int64(2),
  1444. "source_demoE_0_exceptions_total": int64(0),
  1445. "source_demoE_0_records_in_total": int64(6),
  1446. "source_demoE_0_records_out_total": int64(6),
  1447. },
  1448. },
  1449. {
  1450. Name: `TestChanged`,
  1451. Sql: "SELECT changed_cols(\"tt_\", true, color, size) FROM demoE",
  1452. R: [][]map[string]interface{}{
  1453. {{
  1454. "tt_color": "red",
  1455. "tt_size": float64(3),
  1456. }},
  1457. {{
  1458. "tt_color": "blue",
  1459. "tt_size": float64(2),
  1460. }},
  1461. {{
  1462. "tt_color": "yellow",
  1463. "tt_size": float64(4),
  1464. }},
  1465. {{
  1466. "tt_color": "red",
  1467. "tt_size": float64(1),
  1468. }},
  1469. },
  1470. M: map[string]interface{}{
  1471. "op_3_project_0_exceptions_total": int64(0),
  1472. "op_3_project_0_process_latency_us": int64(0),
  1473. "op_3_project_0_records_in_total": int64(4),
  1474. "op_3_project_0_records_out_total": int64(4),
  1475. "sink_mockSink_0_exceptions_total": int64(0),
  1476. "sink_mockSink_0_records_in_total": int64(4),
  1477. "sink_mockSink_0_records_out_total": int64(4),
  1478. "source_demoE_0_exceptions_total": int64(0),
  1479. "source_demoE_0_records_in_total": int64(6),
  1480. "source_demoE_0_records_out_total": int64(6),
  1481. },
  1482. },
  1483. }
  1484. HandleStream(true, streamList, t)
  1485. options := []*api.RuleOption{
  1486. {
  1487. BufferLength: 100,
  1488. SendError: true,
  1489. IsEventTime: true,
  1490. LateTol: 1000,
  1491. }, {
  1492. BufferLength: 100,
  1493. SendError: true,
  1494. Qos: api.AtLeastOnce,
  1495. CheckpointInterval: 5000,
  1496. IsEventTime: true,
  1497. LateTol: 1000,
  1498. }, {
  1499. BufferLength: 100,
  1500. SendError: true,
  1501. Qos: api.ExactlyOnce,
  1502. CheckpointInterval: 5000,
  1503. IsEventTime: true,
  1504. LateTol: 1000,
  1505. },
  1506. }
  1507. for j, opt := range options {
  1508. DoRuleTest(t, tests, j, opt, 0)
  1509. }
  1510. }
  1511. func TestSingleSQLError(t *testing.T) {
  1512. // Reset
  1513. streamList := []string{"ldemo"}
  1514. HandleStream(false, streamList, t)
  1515. // Data setup
  1516. tests := []RuleTest{
  1517. {
  1518. Name: `TestSingleSQLErrorRule1`,
  1519. Sql: `SELECT color, ts FROM ldemo where size >= 3`,
  1520. R: [][]map[string]interface{}{
  1521. {{
  1522. "color": "red",
  1523. "ts": float64(1541152486013),
  1524. }},
  1525. {{
  1526. "error": "run Where error: invalid operation string(string) >= int64(3)",
  1527. }},
  1528. {{
  1529. "ts": float64(1541152487632),
  1530. }},
  1531. },
  1532. M: map[string]interface{}{
  1533. "op_3_project_0_exceptions_total": int64(1),
  1534. "op_3_project_0_process_latency_us": int64(0),
  1535. "op_3_project_0_records_in_total": int64(2),
  1536. "op_3_project_0_records_out_total": int64(2),
  1537. "sink_mockSink_0_exceptions_total": int64(0),
  1538. "sink_mockSink_0_records_in_total": int64(3),
  1539. "sink_mockSink_0_records_out_total": int64(3),
  1540. "source_ldemo_0_exceptions_total": int64(0),
  1541. "source_ldemo_0_records_in_total": int64(5),
  1542. "source_ldemo_0_records_out_total": int64(5),
  1543. "op_2_filter_0_exceptions_total": int64(1),
  1544. "op_2_filter_0_process_latency_us": int64(0),
  1545. "op_2_filter_0_records_in_total": int64(5),
  1546. "op_2_filter_0_records_out_total": int64(2),
  1547. },
  1548. }, {
  1549. Name: `TestSingleSQLErrorRule2`,
  1550. Sql: `SELECT size * 5 FROM ldemo`,
  1551. R: [][]map[string]interface{}{
  1552. {{
  1553. "kuiper_field_0": float64(15),
  1554. }},
  1555. {{
  1556. "error": "run Select error: invalid operation string(string) * int64(5)",
  1557. }},
  1558. {{
  1559. "kuiper_field_0": float64(15),
  1560. }},
  1561. {{
  1562. "kuiper_field_0": float64(10),
  1563. }},
  1564. {{}},
  1565. },
  1566. M: map[string]interface{}{
  1567. "op_2_project_0_exceptions_total": int64(1),
  1568. "op_2_project_0_process_latency_us": int64(0),
  1569. "op_2_project_0_records_in_total": int64(5),
  1570. "op_2_project_0_records_out_total": int64(4),
  1571. "sink_mockSink_0_exceptions_total": int64(0),
  1572. "sink_mockSink_0_records_in_total": int64(5),
  1573. "sink_mockSink_0_records_out_total": int64(5),
  1574. "source_ldemo_0_exceptions_total": int64(0),
  1575. "source_ldemo_0_records_in_total": int64(5),
  1576. "source_ldemo_0_records_out_total": int64(5),
  1577. },
  1578. },
  1579. }
  1580. HandleStream(true, streamList, t)
  1581. DoRuleTest(t, tests, 0, &api.RuleOption{
  1582. BufferLength: 100,
  1583. SendError: true,
  1584. }, 0)
  1585. }
  1586. func TestSingleSQLOmitError(t *testing.T) {
  1587. // Reset
  1588. streamList := []string{"ldemo"}
  1589. HandleStream(false, streamList, t)
  1590. // Data setup
  1591. tests := []RuleTest{
  1592. {
  1593. Name: `TestSingleSQLErrorRule1`,
  1594. Sql: `SELECT color, ts FROM ldemo where size >= 3`,
  1595. R: [][]map[string]interface{}{
  1596. {{
  1597. "color": "red",
  1598. "ts": float64(1541152486013),
  1599. }},
  1600. {{
  1601. "ts": float64(1541152487632),
  1602. }},
  1603. },
  1604. M: map[string]interface{}{
  1605. "op_3_project_0_exceptions_total": int64(0),
  1606. "op_3_project_0_process_latency_us": int64(0),
  1607. "op_3_project_0_records_in_total": int64(2),
  1608. "op_3_project_0_records_out_total": int64(2),
  1609. "sink_mockSink_0_exceptions_total": int64(0),
  1610. "sink_mockSink_0_records_in_total": int64(2),
  1611. "sink_mockSink_0_records_out_total": int64(2),
  1612. "source_ldemo_0_exceptions_total": int64(0),
  1613. "source_ldemo_0_records_in_total": int64(5),
  1614. "source_ldemo_0_records_out_total": int64(5),
  1615. "op_2_filter_0_exceptions_total": int64(1),
  1616. "op_2_filter_0_process_latency_us": int64(0),
  1617. "op_2_filter_0_records_in_total": int64(5),
  1618. "op_2_filter_0_records_out_total": int64(2),
  1619. },
  1620. }, {
  1621. Name: `TestSingleSQLErrorRule2`,
  1622. Sql: `SELECT size * 5 FROM ldemo`,
  1623. R: [][]map[string]interface{}{
  1624. {{
  1625. "kuiper_field_0": float64(15),
  1626. }},
  1627. {{
  1628. "kuiper_field_0": float64(15),
  1629. }},
  1630. {{
  1631. "kuiper_field_0": float64(10),
  1632. }},
  1633. {{}},
  1634. },
  1635. M: map[string]interface{}{
  1636. "op_2_project_0_exceptions_total": int64(1),
  1637. "op_2_project_0_process_latency_us": int64(0),
  1638. "op_2_project_0_records_in_total": int64(5),
  1639. "op_2_project_0_records_out_total": int64(4),
  1640. "sink_mockSink_0_exceptions_total": int64(0),
  1641. "sink_mockSink_0_records_in_total": int64(4),
  1642. "sink_mockSink_0_records_out_total": int64(4),
  1643. "source_ldemo_0_exceptions_total": int64(0),
  1644. "source_ldemo_0_records_in_total": int64(5),
  1645. "source_ldemo_0_records_out_total": int64(5),
  1646. },
  1647. },
  1648. }
  1649. HandleStream(true, streamList, t)
  1650. DoRuleTest(t, tests, 0, &api.RuleOption{
  1651. BufferLength: 100,
  1652. SendError: false,
  1653. }, 0)
  1654. }
  1655. func TestSingleSQLTemplate(t *testing.T) {
  1656. // Reset
  1657. streamList := []string{"demo"}
  1658. HandleStream(false, streamList, t)
  1659. // Data setup
  1660. tests := []RuleTest{
  1661. {
  1662. Name: `TestSingleSQLTemplateRule1`,
  1663. Sql: `SELECT * FROM demo`,
  1664. R: []map[string]interface{}{
  1665. {
  1666. "c": "red",
  1667. "wrapper": "w1",
  1668. },
  1669. {
  1670. "c": "blue",
  1671. "wrapper": "w1",
  1672. },
  1673. {
  1674. "c": "blue",
  1675. "wrapper": "w1",
  1676. },
  1677. {
  1678. "c": "yellow",
  1679. "wrapper": "w1",
  1680. },
  1681. {
  1682. "c": "red",
  1683. "wrapper": "w1",
  1684. },
  1685. },
  1686. M: map[string]interface{}{
  1687. "op_2_project_0_exceptions_total": int64(0),
  1688. "op_2_project_0_process_latency_us": int64(0),
  1689. "op_2_project_0_records_in_total": int64(5),
  1690. "op_2_project_0_records_out_total": int64(5),
  1691. "sink_mockSink_0_exceptions_total": int64(0),
  1692. "sink_mockSink_0_records_in_total": int64(5),
  1693. "sink_mockSink_0_records_out_total": int64(5),
  1694. "source_demo_0_exceptions_total": int64(0),
  1695. "source_demo_0_records_in_total": int64(5),
  1696. "source_demo_0_records_out_total": int64(5),
  1697. },
  1698. },
  1699. }
  1700. HandleStream(true, streamList, t)
  1701. doRuleTestBySinkProps(t, tests, 0, &api.RuleOption{
  1702. BufferLength: 100,
  1703. SendError: true,
  1704. }, 0, map[string]interface{}{
  1705. "dataTemplate": `{"wrapper":"w1", "c":"{{.color}}"}`,
  1706. "sendSingle": true,
  1707. }, func(result [][]byte) interface{} {
  1708. var maps []map[string]interface{}
  1709. for _, v := range result {
  1710. var mapRes map[string]interface{}
  1711. err := json.Unmarshal(v, &mapRes)
  1712. if err != nil {
  1713. t.Errorf("Failed to parse the input into map")
  1714. continue
  1715. }
  1716. maps = append(maps, mapRes)
  1717. }
  1718. return maps
  1719. })
  1720. }
  1721. func TestNoneSingleSQLTemplate(t *testing.T) {
  1722. // Reset
  1723. streamList := []string{"demo"}
  1724. HandleStream(false, streamList, t)
  1725. // Data setup
  1726. tests := []RuleTest{
  1727. {
  1728. Name: `TestNoneSingleSQLTemplateRule1`,
  1729. Sql: `SELECT * FROM demo`,
  1730. R: [][]byte{
  1731. []byte("<div>results</div><ul><li>red - 3</li></ul>"),
  1732. []byte("<div>results</div><ul><li>blue - 6</li></ul>"),
  1733. []byte("<div>results</div><ul><li>blue - 2</li></ul>"),
  1734. []byte("<div>results</div><ul><li>yellow - 4</li></ul>"),
  1735. []byte("<div>results</div><ul><li>red - 1</li></ul>"),
  1736. },
  1737. M: map[string]interface{}{
  1738. "op_2_project_0_exceptions_total": int64(0),
  1739. "op_2_project_0_process_latency_us": int64(0),
  1740. "op_2_project_0_records_in_total": int64(5),
  1741. "op_2_project_0_records_out_total": int64(5),
  1742. "sink_mockSink_0_exceptions_total": int64(0),
  1743. "sink_mockSink_0_records_in_total": int64(5),
  1744. "sink_mockSink_0_records_out_total": int64(5),
  1745. "source_demo_0_exceptions_total": int64(0),
  1746. "source_demo_0_records_in_total": int64(5),
  1747. "source_demo_0_records_out_total": int64(5),
  1748. },
  1749. },
  1750. }
  1751. HandleStream(true, streamList, t)
  1752. doRuleTestBySinkProps(t, tests, 0, &api.RuleOption{
  1753. BufferLength: 100,
  1754. SendError: true,
  1755. }, 0, map[string]interface{}{
  1756. "dataTemplate": `<div>results</div><ul>{{range .}}<li>{{.color}} - {{.size}}</li>{{end}}</ul>`,
  1757. }, func(result [][]byte) interface{} {
  1758. return result
  1759. })
  1760. }
  1761. func TestSingleSQLForBinary(t *testing.T) {
  1762. // Reset
  1763. streamList := []string{"binDemo"}
  1764. HandleStream(false, streamList, t)
  1765. // Data setup
  1766. tests := []RuleTest{
  1767. {
  1768. Name: `TestSingleSQLRule1`,
  1769. Sql: `SELECT * FROM binDemo`,
  1770. R: [][]map[string]interface{}{
  1771. {{
  1772. "self": mocknode.Image,
  1773. }},
  1774. },
  1775. W: 50,
  1776. M: map[string]interface{}{
  1777. "op_2_project_0_exceptions_total": int64(0),
  1778. "op_2_project_0_process_latency_us": int64(0),
  1779. "op_2_project_0_records_in_total": int64(1),
  1780. "op_2_project_0_records_out_total": int64(1),
  1781. "sink_mockSink_0_exceptions_total": int64(0),
  1782. "sink_mockSink_0_records_in_total": int64(1),
  1783. "sink_mockSink_0_records_out_total": int64(1),
  1784. "source_binDemo_0_exceptions_total": int64(0),
  1785. "source_binDemo_0_records_in_total": int64(1),
  1786. "source_binDemo_0_records_out_total": int64(1),
  1787. },
  1788. },
  1789. }
  1790. HandleStream(true, streamList, t)
  1791. options := []*api.RuleOption{
  1792. {
  1793. BufferLength: 100,
  1794. SendError: true,
  1795. }, {
  1796. BufferLength: 100,
  1797. SendError: true,
  1798. Qos: api.AtLeastOnce,
  1799. CheckpointInterval: 5000,
  1800. }, {
  1801. BufferLength: 100,
  1802. SendError: true,
  1803. Qos: api.ExactlyOnce,
  1804. CheckpointInterval: 5000,
  1805. },
  1806. }
  1807. byteFunc := func(result [][]byte) interface{} {
  1808. var maps [][]map[string]interface{}
  1809. for _, v := range result {
  1810. var mapRes []map[string][]byte
  1811. err := json.Unmarshal(v, &mapRes)
  1812. if err != nil {
  1813. panic("Failed to parse the input into map")
  1814. }
  1815. mapInt := make([]map[string]interface{}, len(mapRes))
  1816. for i, mv := range mapRes {
  1817. mapInt[i] = make(map[string]interface{})
  1818. // assume only one key
  1819. for k, v := range mv {
  1820. mapInt[i][k] = v
  1821. }
  1822. }
  1823. maps = append(maps, mapInt)
  1824. }
  1825. return maps
  1826. }
  1827. for j, opt := range options {
  1828. doRuleTestBySinkProps(t, tests, j, opt, 0, nil, byteFunc)
  1829. }
  1830. }
  1831. func TestWindowSQL(t *testing.T) {
  1832. // Reset
  1833. streamList := []string{"demoE"}
  1834. HandleStream(false, streamList, t)
  1835. tests := []RuleTest{
  1836. {
  1837. Name: "TestHoppingWindowSQL1",
  1838. Sql: `select size,color from demoE GROUP BY HOPPINGWINDOW(ss, 3, 5)`,
  1839. R: [][]map[string]interface{}{
  1840. {
  1841. {
  1842. "color": "blue",
  1843. "size": float64(2),
  1844. },
  1845. {
  1846. "color": "red",
  1847. "size": float64(1),
  1848. },
  1849. },
  1850. },
  1851. },
  1852. {
  1853. Name: "TestHoppingWindowSQL2",
  1854. Sql: `select size,color from demoE GROUP BY HOPPINGWINDOW(ss, 1, 2)`,
  1855. R: [][]map[string]interface{}{
  1856. {
  1857. {
  1858. "color": "blue",
  1859. "size": float64(2),
  1860. },
  1861. },
  1862. {
  1863. {
  1864. "color": "red",
  1865. "size": float64(1),
  1866. },
  1867. },
  1868. {},
  1869. },
  1870. },
  1871. {
  1872. Name: "TestHoppingWindowSQL3",
  1873. Sql: `select size,color from demoE GROUP BY HOPPINGWINDOW(ss, 2, 5)`,
  1874. R: [][]map[string]interface{}{
  1875. {
  1876. {
  1877. "color": "red",
  1878. "size": float64(1),
  1879. },
  1880. },
  1881. },
  1882. },
  1883. }
  1884. // Data setup
  1885. HandleStream(true, streamList, t)
  1886. options := []*api.RuleOption{
  1887. {
  1888. BufferLength: 100,
  1889. SendError: true,
  1890. Qos: api.AtLeastOnce,
  1891. CheckpointInterval: 5000,
  1892. IsEventTime: true,
  1893. },
  1894. {
  1895. BufferLength: 100,
  1896. SendError: true,
  1897. Qos: api.ExactlyOnce,
  1898. CheckpointInterval: 5000,
  1899. IsEventTime: true,
  1900. },
  1901. }
  1902. for j, opt := range options {
  1903. DoRuleTest(t, tests, j, opt, 0)
  1904. }
  1905. }
  1906. func TestAliasSQL(t *testing.T) {
  1907. streamList := []string{"demo"}
  1908. HandleStream(false, streamList, t)
  1909. tests := []RuleTest{
  1910. {
  1911. Name: "TestAliasSQL",
  1912. Sql: `select size + 1 as size, size + 1 as b from demo`,
  1913. R: [][]map[string]interface{}{
  1914. {
  1915. {
  1916. "size": float64(4),
  1917. "b": float64(5),
  1918. },
  1919. },
  1920. {
  1921. {
  1922. "size": float64(7),
  1923. "b": float64(8),
  1924. },
  1925. },
  1926. {
  1927. {
  1928. "size": float64(3),
  1929. "b": float64(4),
  1930. },
  1931. },
  1932. {
  1933. {
  1934. "size": float64(5),
  1935. "b": float64(6),
  1936. },
  1937. },
  1938. {
  1939. {
  1940. "size": float64(2),
  1941. "b": float64(3),
  1942. },
  1943. },
  1944. },
  1945. },
  1946. {
  1947. Name: "TestAliasSQL1",
  1948. Sql: `select size as a, a + 1 as b from demo`,
  1949. R: [][]map[string]interface{}{
  1950. {
  1951. {
  1952. "a": float64(3),
  1953. "b": float64(4),
  1954. },
  1955. },
  1956. {
  1957. {
  1958. "a": float64(6),
  1959. "b": float64(7),
  1960. },
  1961. },
  1962. {
  1963. {
  1964. "a": float64(2),
  1965. "b": float64(3),
  1966. },
  1967. },
  1968. {
  1969. {
  1970. "a": float64(4),
  1971. "b": float64(5),
  1972. },
  1973. },
  1974. {
  1975. {
  1976. "a": float64(1),
  1977. "b": float64(2),
  1978. },
  1979. },
  1980. },
  1981. },
  1982. {
  1983. Name: "TestAliasSQL2",
  1984. Sql: `select a + 1 as b, size as a from demo`,
  1985. R: [][]map[string]interface{}{
  1986. {
  1987. {
  1988. "a": float64(3),
  1989. "b": float64(4),
  1990. },
  1991. },
  1992. {
  1993. {
  1994. "a": float64(6),
  1995. "b": float64(7),
  1996. },
  1997. },
  1998. {
  1999. {
  2000. "a": float64(2),
  2001. "b": float64(3),
  2002. },
  2003. },
  2004. {
  2005. {
  2006. "a": float64(4),
  2007. "b": float64(5),
  2008. },
  2009. },
  2010. {
  2011. {
  2012. "a": float64(1),
  2013. "b": float64(2),
  2014. },
  2015. },
  2016. },
  2017. },
  2018. }
  2019. // Data setup
  2020. HandleStream(true, streamList, t)
  2021. options := []*api.RuleOption{
  2022. {
  2023. BufferLength: 100,
  2024. SendError: true,
  2025. Qos: api.AtLeastOnce,
  2026. CheckpointInterval: 5000,
  2027. },
  2028. {
  2029. BufferLength: 100,
  2030. SendError: true,
  2031. Qos: api.ExactlyOnce,
  2032. CheckpointInterval: 5000,
  2033. },
  2034. }
  2035. for j, opt := range options {
  2036. DoRuleTest(t, tests, j, opt, 0)
  2037. }
  2038. }