parser_test.go 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package ottl
  4. import (
  5. "context"
  6. "errors"
  7. "fmt"
  8. "reflect"
  9. "regexp"
  10. "testing"
  11. "time"
  12. "github.com/stretchr/testify/assert"
  13. "go.opentelemetry.io/collector/component/componenttest"
  14. "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/ottltest"
  15. )
  16. // This is not in ottltest because it depends on a type that's a member of OTTL.
  17. func booleanp(b boolean) *boolean {
  18. return &b
  19. }
  20. func Test_parse(t *testing.T) {
  21. tests := []struct {
  22. name string
  23. statement string
  24. expected *parsedStatement
  25. }{
  26. {
  27. name: "editor with string",
  28. statement: `set("foo")`,
  29. expected: &parsedStatement{
  30. Editor: editor{
  31. Function: "set",
  32. Arguments: []argument{
  33. {
  34. Value: value{
  35. String: ottltest.Strp("foo"),
  36. },
  37. },
  38. },
  39. },
  40. WhereClause: nil,
  41. },
  42. },
  43. {
  44. name: "editor with float",
  45. statement: `met(1.2)`,
  46. expected: &parsedStatement{
  47. Editor: editor{
  48. Function: "met",
  49. Arguments: []argument{
  50. {
  51. Value: value{
  52. Literal: &mathExprLiteral{
  53. Float: ottltest.Floatp(1.2),
  54. },
  55. },
  56. },
  57. },
  58. },
  59. WhereClause: nil,
  60. },
  61. },
  62. {
  63. name: "editor with int",
  64. statement: `fff(12)`,
  65. expected: &parsedStatement{
  66. Editor: editor{
  67. Function: "fff",
  68. Arguments: []argument{
  69. {
  70. Value: value{
  71. Literal: &mathExprLiteral{
  72. Int: ottltest.Intp(12),
  73. },
  74. },
  75. },
  76. },
  77. },
  78. WhereClause: nil,
  79. },
  80. },
  81. {
  82. name: "complex editor",
  83. statement: `set("foo", GetSomething(bear.honey))`,
  84. expected: &parsedStatement{
  85. Editor: editor{
  86. Function: "set",
  87. Arguments: []argument{
  88. {
  89. Value: value{
  90. String: ottltest.Strp("foo"),
  91. },
  92. },
  93. {
  94. Value: value{
  95. Literal: &mathExprLiteral{
  96. Converter: &converter{
  97. Function: "GetSomething",
  98. Arguments: []argument{
  99. {
  100. Value: value{
  101. Literal: &mathExprLiteral{
  102. Path: &Path{
  103. Fields: []Field{
  104. {
  105. Name: "bear",
  106. },
  107. {
  108. Name: "honey",
  109. },
  110. },
  111. },
  112. },
  113. },
  114. },
  115. },
  116. },
  117. },
  118. },
  119. },
  120. },
  121. },
  122. WhereClause: nil,
  123. },
  124. },
  125. {
  126. name: "complex path",
  127. statement: `set(foo.attributes["bar"].cat, "dog")`,
  128. expected: &parsedStatement{
  129. Editor: editor{
  130. Function: "set",
  131. Arguments: []argument{
  132. {
  133. Value: value{
  134. Literal: &mathExprLiteral{
  135. Path: &Path{
  136. Fields: []Field{
  137. {
  138. Name: "foo",
  139. },
  140. {
  141. Name: "attributes",
  142. Keys: []Key{
  143. {
  144. String: ottltest.Strp("bar"),
  145. },
  146. },
  147. },
  148. {
  149. Name: "cat",
  150. },
  151. },
  152. },
  153. },
  154. },
  155. },
  156. {
  157. Value: value{
  158. String: ottltest.Strp("dog"),
  159. },
  160. },
  161. },
  162. },
  163. WhereClause: nil,
  164. },
  165. },
  166. {
  167. name: "Converter parameters (All Uppercase)",
  168. statement: `replace_pattern(attributes["message"], "device=*", attributes["device_name"], SHA256)`,
  169. expected: &parsedStatement{
  170. Editor: editor{
  171. Function: "replace_pattern",
  172. Arguments: []argument{
  173. {
  174. Value: value{
  175. Literal: &mathExprLiteral{
  176. Path: &Path{
  177. Fields: []Field{
  178. {
  179. Name: "attributes",
  180. Keys: []Key{
  181. {
  182. String: ottltest.Strp("message"),
  183. },
  184. },
  185. },
  186. },
  187. },
  188. },
  189. },
  190. },
  191. {
  192. Value: value{
  193. String: ottltest.Strp("device=*"),
  194. },
  195. },
  196. {
  197. Value: value{
  198. Literal: &mathExprLiteral{
  199. Path: &Path{
  200. Fields: []Field{
  201. {
  202. Name: "attributes",
  203. Keys: []Key{
  204. {
  205. String: ottltest.Strp("device_name"),
  206. },
  207. },
  208. },
  209. },
  210. },
  211. },
  212. },
  213. },
  214. {
  215. Value: value{
  216. Enum: (*EnumSymbol)(ottltest.Strp("SHA256")),
  217. },
  218. },
  219. },
  220. },
  221. WhereClause: nil,
  222. },
  223. },
  224. {
  225. name: "Converter parameters",
  226. statement: `replace_pattern(attributes["message"], Sha256)`,
  227. expected: &parsedStatement{
  228. Editor: editor{
  229. Function: "replace_pattern",
  230. Arguments: []argument{
  231. {
  232. Value: value{
  233. Literal: &mathExprLiteral{
  234. Path: &Path{
  235. Fields: []Field{
  236. {
  237. Name: "attributes",
  238. Keys: []Key{
  239. {
  240. String: ottltest.Strp("message"),
  241. },
  242. },
  243. },
  244. },
  245. },
  246. },
  247. },
  248. },
  249. {
  250. Value: value{
  251. FunctionName: (ottltest.Strp("Sha256")),
  252. },
  253. },
  254. },
  255. },
  256. WhereClause: nil,
  257. },
  258. },
  259. {
  260. name: "Converter parameters (One Uppercase symbol)",
  261. statement: `replace_pattern(attributes["message"], S)`,
  262. expected: &parsedStatement{
  263. Editor: editor{
  264. Function: "replace_pattern",
  265. Arguments: []argument{
  266. {
  267. Value: value{
  268. Literal: &mathExprLiteral{
  269. Path: &Path{
  270. Fields: []Field{
  271. {
  272. Name: "attributes",
  273. Keys: []Key{
  274. {
  275. String: ottltest.Strp("message"),
  276. },
  277. },
  278. },
  279. },
  280. },
  281. },
  282. },
  283. },
  284. {
  285. Value: value{
  286. Enum: (*EnumSymbol)(ottltest.Strp("S")),
  287. },
  288. },
  289. },
  290. },
  291. WhereClause: nil,
  292. },
  293. },
  294. {
  295. name: "complex path",
  296. statement: `set(foo.bar["x"]["y"].z, Test()[0]["pass"])`,
  297. expected: &parsedStatement{
  298. Editor: editor{
  299. Function: "set",
  300. Arguments: []argument{
  301. {
  302. Value: value{
  303. Literal: &mathExprLiteral{
  304. Path: &Path{
  305. Fields: []Field{
  306. {
  307. Name: "foo",
  308. },
  309. {
  310. Name: "bar",
  311. Keys: []Key{
  312. {
  313. String: ottltest.Strp("x"),
  314. },
  315. {
  316. String: ottltest.Strp("y"),
  317. },
  318. },
  319. },
  320. {
  321. Name: "z",
  322. },
  323. },
  324. },
  325. },
  326. },
  327. },
  328. {
  329. Value: value{
  330. Literal: &mathExprLiteral{
  331. Converter: &converter{
  332. Function: "Test",
  333. Keys: []Key{
  334. {
  335. Int: ottltest.Intp(0),
  336. },
  337. {
  338. String: ottltest.Strp("pass"),
  339. },
  340. },
  341. },
  342. },
  343. },
  344. },
  345. },
  346. },
  347. WhereClause: nil,
  348. },
  349. },
  350. {
  351. name: "where == clause",
  352. statement: `set(foo.attributes["bar"].cat, "dog") where name == "fido"`,
  353. expected: &parsedStatement{
  354. Editor: editor{
  355. Function: "set",
  356. Arguments: []argument{
  357. {
  358. Value: value{
  359. Literal: &mathExprLiteral{
  360. Path: &Path{
  361. Fields: []Field{
  362. {
  363. Name: "foo",
  364. },
  365. {
  366. Name: "attributes",
  367. Keys: []Key{
  368. {
  369. String: ottltest.Strp("bar"),
  370. },
  371. },
  372. },
  373. {
  374. Name: "cat",
  375. },
  376. },
  377. },
  378. },
  379. },
  380. },
  381. {
  382. Value: value{
  383. String: ottltest.Strp("dog"),
  384. },
  385. },
  386. },
  387. },
  388. WhereClause: &booleanExpression{
  389. Left: &term{
  390. Left: &booleanValue{
  391. Comparison: &comparison{
  392. Left: value{
  393. Literal: &mathExprLiteral{
  394. Path: &Path{
  395. Fields: []Field{
  396. {
  397. Name: "name",
  398. },
  399. },
  400. },
  401. },
  402. },
  403. Op: EQ,
  404. Right: value{
  405. String: ottltest.Strp("fido"),
  406. },
  407. },
  408. },
  409. },
  410. },
  411. },
  412. },
  413. {
  414. name: "where != clause",
  415. statement: `set(foo.attributes["bar"].cat, "dog") where name != "fido"`,
  416. expected: &parsedStatement{
  417. Editor: editor{
  418. Function: "set",
  419. Arguments: []argument{
  420. {
  421. Value: value{
  422. Literal: &mathExprLiteral{
  423. Path: &Path{
  424. Fields: []Field{
  425. {
  426. Name: "foo",
  427. },
  428. {
  429. Name: "attributes",
  430. Keys: []Key{
  431. {
  432. String: ottltest.Strp("bar"),
  433. },
  434. },
  435. },
  436. {
  437. Name: "cat",
  438. },
  439. },
  440. },
  441. },
  442. },
  443. },
  444. {
  445. Value: value{
  446. String: ottltest.Strp("dog"),
  447. },
  448. },
  449. },
  450. },
  451. WhereClause: &booleanExpression{
  452. Left: &term{
  453. Left: &booleanValue{
  454. Comparison: &comparison{
  455. Left: value{
  456. Literal: &mathExprLiteral{
  457. Path: &Path{
  458. Fields: []Field{
  459. {
  460. Name: "name",
  461. },
  462. },
  463. },
  464. },
  465. },
  466. Op: NE,
  467. Right: value{
  468. String: ottltest.Strp("fido"),
  469. },
  470. },
  471. },
  472. },
  473. },
  474. },
  475. },
  476. {
  477. name: "ignore extra spaces",
  478. statement: `set ( foo.attributes[ "bar"].cat, "dog") where name=="fido"`,
  479. expected: &parsedStatement{
  480. Editor: editor{
  481. Function: "set",
  482. Arguments: []argument{
  483. {
  484. Value: value{
  485. Literal: &mathExprLiteral{
  486. Path: &Path{
  487. Fields: []Field{
  488. {
  489. Name: "foo",
  490. },
  491. {
  492. Name: "attributes",
  493. Keys: []Key{
  494. {
  495. String: ottltest.Strp("bar"),
  496. },
  497. },
  498. },
  499. {
  500. Name: "cat",
  501. },
  502. },
  503. },
  504. },
  505. },
  506. },
  507. {
  508. Value: value{
  509. String: ottltest.Strp("dog"),
  510. },
  511. },
  512. },
  513. },
  514. WhereClause: &booleanExpression{
  515. Left: &term{
  516. Left: &booleanValue{
  517. Comparison: &comparison{
  518. Left: value{
  519. Literal: &mathExprLiteral{
  520. Path: &Path{
  521. Fields: []Field{
  522. {
  523. Name: "name",
  524. },
  525. },
  526. },
  527. },
  528. },
  529. Op: EQ,
  530. Right: value{
  531. String: ottltest.Strp("fido"),
  532. },
  533. },
  534. },
  535. },
  536. },
  537. },
  538. },
  539. {
  540. name: "handle quotes",
  541. statement: `set("fo\"o")`,
  542. expected: &parsedStatement{
  543. Editor: editor{
  544. Function: "set",
  545. Arguments: []argument{
  546. {
  547. Value: value{
  548. String: ottltest.Strp("fo\"o"),
  549. },
  550. },
  551. },
  552. },
  553. WhereClause: nil,
  554. },
  555. },
  556. {
  557. name: "editor with boolean false",
  558. statement: `convert_gauge_to_sum("cumulative", false)`,
  559. expected: &parsedStatement{
  560. Editor: editor{
  561. Function: "convert_gauge_to_sum",
  562. Arguments: []argument{
  563. {
  564. Value: value{
  565. String: ottltest.Strp("cumulative"),
  566. },
  567. },
  568. {
  569. Value: value{
  570. Bool: (*boolean)(ottltest.Boolp(false)),
  571. },
  572. },
  573. },
  574. },
  575. WhereClause: nil,
  576. },
  577. },
  578. {
  579. name: "editor with boolean true",
  580. statement: `convert_gauge_to_sum("cumulative", true)`,
  581. expected: &parsedStatement{
  582. Editor: editor{
  583. Function: "convert_gauge_to_sum",
  584. Arguments: []argument{
  585. {
  586. Value: value{
  587. String: ottltest.Strp("cumulative"),
  588. },
  589. },
  590. {
  591. Value: value{
  592. Bool: (*boolean)(ottltest.Boolp(true)),
  593. },
  594. },
  595. },
  596. },
  597. WhereClause: nil,
  598. },
  599. },
  600. {
  601. name: "editor with bytes",
  602. statement: `set(attributes["bytes"], 0x0102030405060708)`,
  603. expected: &parsedStatement{
  604. Editor: editor{
  605. Function: "set",
  606. Arguments: []argument{
  607. {
  608. Value: value{
  609. Literal: &mathExprLiteral{
  610. Path: &Path{
  611. Fields: []Field{
  612. {
  613. Name: "attributes",
  614. Keys: []Key{
  615. {
  616. String: ottltest.Strp("bytes"),
  617. },
  618. },
  619. },
  620. },
  621. },
  622. },
  623. },
  624. },
  625. {
  626. Value: value{
  627. Bytes: (*byteSlice)(&[]byte{1, 2, 3, 4, 5, 6, 7, 8}),
  628. },
  629. },
  630. },
  631. },
  632. WhereClause: nil,
  633. },
  634. },
  635. {
  636. name: "editor with nil",
  637. statement: `set(attributes["test"], nil)`,
  638. expected: &parsedStatement{
  639. Editor: editor{
  640. Function: "set",
  641. Arguments: []argument{
  642. {
  643. Value: value{
  644. Literal: &mathExprLiteral{
  645. Path: &Path{
  646. Fields: []Field{
  647. {
  648. Name: "attributes",
  649. Keys: []Key{
  650. {
  651. String: ottltest.Strp("test"),
  652. },
  653. },
  654. },
  655. },
  656. },
  657. },
  658. },
  659. },
  660. {
  661. Value: value{
  662. IsNil: (*isNil)(ottltest.Boolp(true)),
  663. },
  664. },
  665. },
  666. },
  667. WhereClause: nil,
  668. },
  669. },
  670. {
  671. name: "editor with Enum",
  672. statement: `set(attributes["test"], TEST_ENUM)`,
  673. expected: &parsedStatement{
  674. Editor: editor{
  675. Function: "set",
  676. Arguments: []argument{
  677. {
  678. Value: value{
  679. Literal: &mathExprLiteral{
  680. Path: &Path{
  681. Fields: []Field{
  682. {
  683. Name: "attributes",
  684. Keys: []Key{
  685. {
  686. String: ottltest.Strp("test"),
  687. },
  688. },
  689. },
  690. },
  691. },
  692. },
  693. },
  694. },
  695. {
  696. Value: value{
  697. Enum: (*EnumSymbol)(ottltest.Strp("TEST_ENUM")),
  698. },
  699. },
  700. },
  701. },
  702. WhereClause: nil,
  703. },
  704. },
  705. {
  706. name: "Converter with empty list",
  707. statement: `set(attributes["test"], [])`,
  708. expected: &parsedStatement{
  709. Editor: editor{
  710. Function: "set",
  711. Arguments: []argument{
  712. {
  713. Value: value{
  714. Literal: &mathExprLiteral{
  715. Path: &Path{
  716. Fields: []Field{
  717. {
  718. Name: "attributes",
  719. Keys: []Key{
  720. {
  721. String: ottltest.Strp("test"),
  722. },
  723. },
  724. },
  725. },
  726. },
  727. },
  728. },
  729. },
  730. {
  731. Value: value{
  732. List: &list{
  733. Values: nil,
  734. },
  735. },
  736. },
  737. },
  738. },
  739. WhereClause: nil,
  740. },
  741. },
  742. {
  743. name: "Converter with single-value list",
  744. statement: `set(attributes["test"], ["value0"])`,
  745. expected: &parsedStatement{
  746. Editor: editor{
  747. Function: "set",
  748. Arguments: []argument{
  749. {
  750. Value: value{
  751. Literal: &mathExprLiteral{
  752. Path: &Path{
  753. Fields: []Field{
  754. {
  755. Name: "attributes",
  756. Keys: []Key{
  757. {
  758. String: ottltest.Strp("test"),
  759. },
  760. },
  761. },
  762. },
  763. },
  764. },
  765. },
  766. },
  767. {
  768. Value: value{
  769. List: &list{
  770. Values: []value{
  771. {
  772. String: ottltest.Strp("value0"),
  773. },
  774. },
  775. },
  776. },
  777. },
  778. },
  779. },
  780. WhereClause: nil,
  781. },
  782. },
  783. {
  784. name: "Converter with multi-value list",
  785. statement: `set(attributes["test"], ["value1", "value2"])`,
  786. expected: &parsedStatement{
  787. Editor: editor{
  788. Function: "set",
  789. Arguments: []argument{
  790. {
  791. Value: value{
  792. Literal: &mathExprLiteral{
  793. Path: &Path{
  794. Fields: []Field{
  795. {
  796. Name: "attributes",
  797. Keys: []Key{
  798. {
  799. String: ottltest.Strp("test"),
  800. },
  801. },
  802. },
  803. },
  804. },
  805. },
  806. },
  807. },
  808. {
  809. Value: value{
  810. List: &list{
  811. Values: []value{
  812. {
  813. String: ottltest.Strp("value1"),
  814. },
  815. {
  816. String: ottltest.Strp("value2"),
  817. },
  818. },
  819. },
  820. },
  821. },
  822. },
  823. },
  824. WhereClause: nil,
  825. },
  826. },
  827. {
  828. name: "Converter with nested heterogeneous types",
  829. statement: `set(attributes["test"], [Concat(["a", "b"], "+"), ["1", 2, 3.0], nil, attributes["test"]])`,
  830. expected: &parsedStatement{
  831. Editor: editor{
  832. Function: "set",
  833. Arguments: []argument{
  834. {
  835. Value: value{
  836. Literal: &mathExprLiteral{
  837. Path: &Path{
  838. Fields: []Field{
  839. {
  840. Name: "attributes",
  841. Keys: []Key{
  842. {
  843. String: ottltest.Strp("test"),
  844. },
  845. },
  846. },
  847. },
  848. },
  849. },
  850. },
  851. },
  852. {
  853. Value: value{
  854. List: &list{
  855. Values: []value{
  856. {
  857. Literal: &mathExprLiteral{
  858. Converter: &converter{
  859. Function: "Concat",
  860. Arguments: []argument{
  861. {
  862. Value: value{
  863. List: &list{
  864. Values: []value{
  865. {
  866. String: ottltest.Strp("a"),
  867. },
  868. {
  869. String: ottltest.Strp("b"),
  870. },
  871. },
  872. },
  873. },
  874. },
  875. {
  876. Value: value{
  877. String: ottltest.Strp("+"),
  878. },
  879. },
  880. },
  881. },
  882. },
  883. },
  884. {
  885. List: &list{
  886. Values: []value{
  887. {
  888. String: ottltest.Strp("1"),
  889. },
  890. {
  891. Literal: &mathExprLiteral{
  892. Int: ottltest.Intp(2),
  893. },
  894. },
  895. {
  896. Literal: &mathExprLiteral{
  897. Float: ottltest.Floatp(3.0),
  898. },
  899. },
  900. },
  901. },
  902. },
  903. {
  904. IsNil: (*isNil)(ottltest.Boolp(true)),
  905. },
  906. {
  907. Literal: &mathExprLiteral{
  908. Path: &Path{
  909. Fields: []Field{
  910. {
  911. Name: "attributes",
  912. Keys: []Key{
  913. {
  914. String: ottltest.Strp("test"),
  915. },
  916. },
  917. },
  918. },
  919. },
  920. },
  921. },
  922. },
  923. },
  924. },
  925. },
  926. },
  927. },
  928. WhereClause: nil,
  929. },
  930. },
  931. {
  932. name: "Converter math mathExpression",
  933. statement: `set(attributes["test"], 1000 - 600) where 1 + 1 * 2 == three / One()`,
  934. expected: &parsedStatement{
  935. Editor: editor{
  936. Function: "set",
  937. Arguments: []argument{
  938. {
  939. Value: value{
  940. Literal: &mathExprLiteral{
  941. Path: &Path{
  942. Fields: []Field{
  943. {
  944. Name: "attributes",
  945. Keys: []Key{
  946. {
  947. String: ottltest.Strp("test"),
  948. },
  949. },
  950. },
  951. },
  952. },
  953. },
  954. },
  955. },
  956. {
  957. Value: value{
  958. MathExpression: &mathExpression{
  959. Left: &addSubTerm{
  960. Left: &mathValue{
  961. Literal: &mathExprLiteral{
  962. Int: ottltest.Intp(1000),
  963. },
  964. },
  965. },
  966. Right: []*opAddSubTerm{
  967. {
  968. Operator: SUB,
  969. Term: &addSubTerm{
  970. Left: &mathValue{
  971. Literal: &mathExprLiteral{
  972. Int: ottltest.Intp(600),
  973. },
  974. },
  975. },
  976. },
  977. },
  978. },
  979. },
  980. },
  981. },
  982. },
  983. WhereClause: &booleanExpression{
  984. Left: &term{
  985. Left: &booleanValue{
  986. Comparison: &comparison{
  987. Left: value{
  988. MathExpression: &mathExpression{
  989. Left: &addSubTerm{
  990. Left: &mathValue{
  991. Literal: &mathExprLiteral{
  992. Int: ottltest.Intp(1),
  993. },
  994. },
  995. },
  996. Right: []*opAddSubTerm{
  997. {
  998. Operator: ADD,
  999. Term: &addSubTerm{
  1000. Left: &mathValue{
  1001. Literal: &mathExprLiteral{
  1002. Int: ottltest.Intp(1),
  1003. },
  1004. },
  1005. Right: []*opMultDivValue{
  1006. {
  1007. Operator: MULT,
  1008. Value: &mathValue{
  1009. Literal: &mathExprLiteral{
  1010. Int: ottltest.Intp(2),
  1011. },
  1012. },
  1013. },
  1014. },
  1015. },
  1016. },
  1017. },
  1018. },
  1019. },
  1020. Op: EQ,
  1021. Right: value{
  1022. MathExpression: &mathExpression{
  1023. Left: &addSubTerm{
  1024. Left: &mathValue{
  1025. Literal: &mathExprLiteral{
  1026. Path: &Path{
  1027. Fields: []Field{
  1028. {
  1029. Name: "three",
  1030. },
  1031. },
  1032. },
  1033. },
  1034. },
  1035. Right: []*opMultDivValue{
  1036. {
  1037. Operator: DIV,
  1038. Value: &mathValue{
  1039. Literal: &mathExprLiteral{
  1040. Converter: &converter{
  1041. Function: "One",
  1042. },
  1043. },
  1044. },
  1045. },
  1046. },
  1047. },
  1048. },
  1049. },
  1050. },
  1051. },
  1052. },
  1053. },
  1054. },
  1055. },
  1056. {
  1057. name: "editor with named arg",
  1058. statement: `set(name="foo")`,
  1059. expected: &parsedStatement{
  1060. Editor: editor{
  1061. Function: "set",
  1062. Arguments: []argument{
  1063. {
  1064. Name: "name",
  1065. Value: value{
  1066. String: ottltest.Strp("foo"),
  1067. },
  1068. },
  1069. },
  1070. },
  1071. WhereClause: nil,
  1072. },
  1073. },
  1074. }
  1075. for _, tt := range tests {
  1076. t.Run(tt.statement, func(t *testing.T) {
  1077. parsed, err := parseStatement(tt.statement)
  1078. assert.NoError(t, err)
  1079. assert.EqualValues(t, tt.expected, parsed)
  1080. })
  1081. }
  1082. }
  1083. func Test_parseCondition_full(t *testing.T) {
  1084. tests := []struct {
  1085. name string
  1086. condition string
  1087. expected *booleanExpression
  1088. }{
  1089. {
  1090. name: "where == clause",
  1091. condition: `name == "fido"`,
  1092. expected: &booleanExpression{
  1093. Left: &term{
  1094. Left: &booleanValue{
  1095. Comparison: &comparison{
  1096. Left: value{
  1097. Literal: &mathExprLiteral{
  1098. Path: &Path{
  1099. Fields: []Field{
  1100. {
  1101. Name: "name",
  1102. },
  1103. },
  1104. },
  1105. },
  1106. },
  1107. Op: EQ,
  1108. Right: value{
  1109. String: ottltest.Strp("fido"),
  1110. },
  1111. },
  1112. },
  1113. },
  1114. },
  1115. },
  1116. {
  1117. name: "where != clause",
  1118. condition: `name != "fido"`,
  1119. expected: &booleanExpression{
  1120. Left: &term{
  1121. Left: &booleanValue{
  1122. Comparison: &comparison{
  1123. Left: value{
  1124. Literal: &mathExprLiteral{
  1125. Path: &Path{
  1126. Fields: []Field{
  1127. {
  1128. Name: "name",
  1129. },
  1130. },
  1131. },
  1132. },
  1133. },
  1134. Op: NE,
  1135. Right: value{
  1136. String: ottltest.Strp("fido"),
  1137. },
  1138. },
  1139. },
  1140. },
  1141. },
  1142. },
  1143. {
  1144. name: "Converter math mathExpression",
  1145. condition: `1 + 1 * 2 == three / One()`,
  1146. expected: &booleanExpression{
  1147. Left: &term{
  1148. Left: &booleanValue{
  1149. Comparison: &comparison{
  1150. Left: value{
  1151. MathExpression: &mathExpression{
  1152. Left: &addSubTerm{
  1153. Left: &mathValue{
  1154. Literal: &mathExprLiteral{
  1155. Int: ottltest.Intp(1),
  1156. },
  1157. },
  1158. },
  1159. Right: []*opAddSubTerm{
  1160. {
  1161. Operator: ADD,
  1162. Term: &addSubTerm{
  1163. Left: &mathValue{
  1164. Literal: &mathExprLiteral{
  1165. Int: ottltest.Intp(1),
  1166. },
  1167. },
  1168. Right: []*opMultDivValue{
  1169. {
  1170. Operator: MULT,
  1171. Value: &mathValue{
  1172. Literal: &mathExprLiteral{
  1173. Int: ottltest.Intp(2),
  1174. },
  1175. },
  1176. },
  1177. },
  1178. },
  1179. },
  1180. },
  1181. },
  1182. },
  1183. Op: EQ,
  1184. Right: value{
  1185. MathExpression: &mathExpression{
  1186. Left: &addSubTerm{
  1187. Left: &mathValue{
  1188. Literal: &mathExprLiteral{
  1189. Path: &Path{
  1190. Fields: []Field{
  1191. {
  1192. Name: "three",
  1193. },
  1194. },
  1195. },
  1196. },
  1197. },
  1198. Right: []*opMultDivValue{
  1199. {
  1200. Operator: DIV,
  1201. Value: &mathValue{
  1202. Literal: &mathExprLiteral{
  1203. Converter: &converter{
  1204. Function: "One",
  1205. },
  1206. },
  1207. },
  1208. },
  1209. },
  1210. },
  1211. },
  1212. },
  1213. },
  1214. },
  1215. },
  1216. },
  1217. },
  1218. }
  1219. for _, tt := range tests {
  1220. t.Run(tt.condition, func(t *testing.T) {
  1221. parsed, err := parseCondition(tt.condition)
  1222. assert.NoError(t, err)
  1223. assert.EqualValues(t, tt.expected, parsed)
  1224. })
  1225. }
  1226. }
  1227. func testParsePath(val *Path) (GetSetter[any], error) {
  1228. if val != nil && len(val.Fields) > 0 && (val.Fields[0].Name == "name" || val.Fields[0].Name == "attributes") {
  1229. return &StandardGetSetter[any]{
  1230. Getter: func(ctx context.Context, tCtx any) (any, error) {
  1231. return tCtx, nil
  1232. },
  1233. Setter: func(ctx context.Context, tCtx any, val any) error {
  1234. reflect.DeepEqual(tCtx, val)
  1235. return nil
  1236. },
  1237. }, nil
  1238. }
  1239. if val.Fields[0].Name == "dur1" || val.Fields[0].Name == "dur2" {
  1240. return &StandardGetSetter[any]{
  1241. Getter: func(ctx context.Context, tCtx any) (any, error) {
  1242. m, ok := tCtx.(map[string]time.Duration)
  1243. if !ok {
  1244. return nil, fmt.Errorf("unable to convert transform context to map of strings to times")
  1245. }
  1246. return m[val.Fields[0].Name], nil
  1247. },
  1248. Setter: func(ctx context.Context, tCtx any, val any) error {
  1249. reflect.DeepEqual(tCtx, val)
  1250. return nil
  1251. },
  1252. }, nil
  1253. }
  1254. if val.Fields[0].Name == "time1" || val.Fields[0].Name == "time2" {
  1255. return &StandardGetSetter[any]{
  1256. Getter: func(ctx context.Context, tCtx any) (any, error) {
  1257. m, ok := tCtx.(map[string]time.Time)
  1258. if !ok {
  1259. return nil, fmt.Errorf("unable to convert transform context to map of strings to times")
  1260. }
  1261. return m[val.Fields[0].Name], nil
  1262. },
  1263. Setter: func(ctx context.Context, tCtx any, val any) error {
  1264. reflect.DeepEqual(tCtx, val)
  1265. return nil
  1266. },
  1267. }, nil
  1268. }
  1269. return nil, fmt.Errorf("bad path %v", val)
  1270. }
  1271. // Helper for test cases where the WHERE clause is all that matters.
  1272. // Parse string should start with `set(name, "test") where`...
  1273. func setNameTest(b *booleanExpression) *parsedStatement {
  1274. return &parsedStatement{
  1275. Editor: editor{
  1276. Function: "set",
  1277. Arguments: []argument{
  1278. {
  1279. Value: value{
  1280. Literal: &mathExprLiteral{
  1281. Path: &Path{
  1282. Fields: []Field{
  1283. {
  1284. Name: "name",
  1285. },
  1286. },
  1287. },
  1288. },
  1289. },
  1290. },
  1291. {
  1292. Value: value{
  1293. String: ottltest.Strp("test"),
  1294. },
  1295. },
  1296. },
  1297. },
  1298. WhereClause: b,
  1299. }
  1300. }
  1301. func Test_parseWhere(t *testing.T) {
  1302. tests := []struct {
  1303. statement string
  1304. expected *parsedStatement
  1305. }{
  1306. {
  1307. statement: `true`,
  1308. expected: setNameTest(&booleanExpression{
  1309. Left: &term{
  1310. Left: &booleanValue{
  1311. ConstExpr: &constExpr{
  1312. Boolean: booleanp(true),
  1313. },
  1314. },
  1315. },
  1316. }),
  1317. },
  1318. {
  1319. statement: `true and false`,
  1320. expected: setNameTest(&booleanExpression{
  1321. Left: &term{
  1322. Left: &booleanValue{
  1323. ConstExpr: &constExpr{
  1324. Boolean: booleanp(true),
  1325. },
  1326. },
  1327. Right: []*opAndBooleanValue{
  1328. {
  1329. Operator: "and",
  1330. Value: &booleanValue{
  1331. ConstExpr: &constExpr{
  1332. Boolean: booleanp(false),
  1333. },
  1334. },
  1335. },
  1336. },
  1337. },
  1338. }),
  1339. },
  1340. {
  1341. statement: `true and true and false`,
  1342. expected: setNameTest(&booleanExpression{
  1343. Left: &term{
  1344. Left: &booleanValue{
  1345. ConstExpr: &constExpr{
  1346. Boolean: booleanp(true),
  1347. },
  1348. },
  1349. Right: []*opAndBooleanValue{
  1350. {
  1351. Operator: "and",
  1352. Value: &booleanValue{
  1353. ConstExpr: &constExpr{
  1354. Boolean: booleanp(true),
  1355. },
  1356. },
  1357. },
  1358. {
  1359. Operator: "and",
  1360. Value: &booleanValue{
  1361. ConstExpr: &constExpr{
  1362. Boolean: booleanp(false),
  1363. },
  1364. },
  1365. },
  1366. },
  1367. },
  1368. }),
  1369. },
  1370. {
  1371. statement: `true or false`,
  1372. expected: setNameTest(&booleanExpression{
  1373. Left: &term{
  1374. Left: &booleanValue{
  1375. ConstExpr: &constExpr{
  1376. Boolean: booleanp(true),
  1377. },
  1378. },
  1379. },
  1380. Right: []*opOrTerm{
  1381. {
  1382. Operator: "or",
  1383. Term: &term{
  1384. Left: &booleanValue{
  1385. ConstExpr: &constExpr{
  1386. Boolean: booleanp(false),
  1387. },
  1388. },
  1389. },
  1390. },
  1391. },
  1392. }),
  1393. },
  1394. {
  1395. statement: `false and true or false`,
  1396. expected: setNameTest(&booleanExpression{
  1397. Left: &term{
  1398. Left: &booleanValue{
  1399. ConstExpr: &constExpr{
  1400. Boolean: booleanp(false),
  1401. },
  1402. },
  1403. Right: []*opAndBooleanValue{
  1404. {
  1405. Operator: "and",
  1406. Value: &booleanValue{
  1407. ConstExpr: &constExpr{
  1408. Boolean: booleanp(true),
  1409. },
  1410. },
  1411. },
  1412. },
  1413. },
  1414. Right: []*opOrTerm{
  1415. {
  1416. Operator: "or",
  1417. Term: &term{
  1418. Left: &booleanValue{
  1419. ConstExpr: &constExpr{
  1420. Boolean: booleanp(false),
  1421. },
  1422. },
  1423. },
  1424. },
  1425. },
  1426. }),
  1427. },
  1428. {
  1429. statement: `(false and true) or false`,
  1430. expected: setNameTest(&booleanExpression{
  1431. Left: &term{
  1432. Left: &booleanValue{
  1433. SubExpr: &booleanExpression{
  1434. Left: &term{
  1435. Left: &booleanValue{
  1436. ConstExpr: &constExpr{
  1437. Boolean: booleanp(false),
  1438. },
  1439. },
  1440. Right: []*opAndBooleanValue{
  1441. {
  1442. Operator: "and",
  1443. Value: &booleanValue{
  1444. ConstExpr: &constExpr{
  1445. Boolean: booleanp(true),
  1446. },
  1447. },
  1448. },
  1449. },
  1450. },
  1451. },
  1452. },
  1453. },
  1454. Right: []*opOrTerm{
  1455. {
  1456. Operator: "or",
  1457. Term: &term{
  1458. Left: &booleanValue{
  1459. ConstExpr: &constExpr{
  1460. Boolean: booleanp(false),
  1461. },
  1462. },
  1463. },
  1464. },
  1465. },
  1466. }),
  1467. },
  1468. {
  1469. statement: `false and (true or false)`,
  1470. expected: setNameTest(&booleanExpression{
  1471. Left: &term{
  1472. Left: &booleanValue{
  1473. ConstExpr: &constExpr{
  1474. Boolean: booleanp(false),
  1475. },
  1476. },
  1477. Right: []*opAndBooleanValue{
  1478. {
  1479. Operator: "and",
  1480. Value: &booleanValue{
  1481. SubExpr: &booleanExpression{
  1482. Left: &term{
  1483. Left: &booleanValue{
  1484. ConstExpr: &constExpr{
  1485. Boolean: booleanp(true),
  1486. },
  1487. },
  1488. },
  1489. Right: []*opOrTerm{
  1490. {
  1491. Operator: "or",
  1492. Term: &term{
  1493. Left: &booleanValue{
  1494. ConstExpr: &constExpr{
  1495. Boolean: booleanp(false),
  1496. },
  1497. },
  1498. },
  1499. },
  1500. },
  1501. },
  1502. },
  1503. },
  1504. },
  1505. },
  1506. }),
  1507. },
  1508. {
  1509. statement: `name != "foo" and name != "bar"`,
  1510. expected: setNameTest(&booleanExpression{
  1511. Left: &term{
  1512. Left: &booleanValue{
  1513. Comparison: &comparison{
  1514. Left: value{
  1515. Literal: &mathExprLiteral{
  1516. Path: &Path{
  1517. Fields: []Field{
  1518. {
  1519. Name: "name",
  1520. },
  1521. },
  1522. },
  1523. },
  1524. },
  1525. Op: NE,
  1526. Right: value{
  1527. String: ottltest.Strp("foo"),
  1528. },
  1529. },
  1530. },
  1531. Right: []*opAndBooleanValue{
  1532. {
  1533. Operator: "and",
  1534. Value: &booleanValue{
  1535. Comparison: &comparison{
  1536. Left: value{
  1537. Literal: &mathExprLiteral{
  1538. Path: &Path{
  1539. Fields: []Field{
  1540. {
  1541. Name: "name",
  1542. },
  1543. },
  1544. },
  1545. },
  1546. },
  1547. Op: NE,
  1548. Right: value{
  1549. String: ottltest.Strp("bar"),
  1550. },
  1551. },
  1552. },
  1553. },
  1554. },
  1555. },
  1556. }),
  1557. },
  1558. {
  1559. statement: `name == "foo" or name == "bar"`,
  1560. expected: setNameTest(&booleanExpression{
  1561. Left: &term{
  1562. Left: &booleanValue{
  1563. Comparison: &comparison{
  1564. Left: value{
  1565. Literal: &mathExprLiteral{
  1566. Path: &Path{
  1567. Fields: []Field{
  1568. {
  1569. Name: "name",
  1570. },
  1571. },
  1572. },
  1573. },
  1574. },
  1575. Op: EQ,
  1576. Right: value{
  1577. String: ottltest.Strp("foo"),
  1578. },
  1579. },
  1580. },
  1581. },
  1582. Right: []*opOrTerm{
  1583. {
  1584. Operator: "or",
  1585. Term: &term{
  1586. Left: &booleanValue{
  1587. Comparison: &comparison{
  1588. Left: value{
  1589. Literal: &mathExprLiteral{
  1590. Path: &Path{
  1591. Fields: []Field{
  1592. {
  1593. Name: "name",
  1594. },
  1595. },
  1596. },
  1597. },
  1598. },
  1599. Op: EQ,
  1600. Right: value{
  1601. String: ottltest.Strp("bar"),
  1602. },
  1603. },
  1604. },
  1605. },
  1606. },
  1607. },
  1608. }),
  1609. },
  1610. {
  1611. statement: `true and not false`,
  1612. expected: setNameTest(&booleanExpression{
  1613. Left: &term{
  1614. Left: &booleanValue{
  1615. ConstExpr: &constExpr{
  1616. Boolean: booleanp(true),
  1617. },
  1618. },
  1619. Right: []*opAndBooleanValue{
  1620. {
  1621. Operator: "and",
  1622. Value: &booleanValue{
  1623. Negation: ottltest.Strp("not"),
  1624. ConstExpr: &constExpr{
  1625. Boolean: booleanp(false),
  1626. },
  1627. },
  1628. },
  1629. },
  1630. },
  1631. }),
  1632. },
  1633. {
  1634. statement: `not name == "bar"`,
  1635. expected: setNameTest(&booleanExpression{
  1636. Left: &term{
  1637. Left: &booleanValue{
  1638. Negation: ottltest.Strp("not"),
  1639. Comparison: &comparison{
  1640. Left: value{
  1641. Literal: &mathExprLiteral{
  1642. Path: &Path{
  1643. Fields: []Field{
  1644. {
  1645. Name: "name",
  1646. },
  1647. },
  1648. },
  1649. },
  1650. },
  1651. Op: EQ,
  1652. Right: value{
  1653. String: ottltest.Strp("bar"),
  1654. },
  1655. },
  1656. },
  1657. },
  1658. }),
  1659. },
  1660. {
  1661. statement: `not (true or false)`,
  1662. expected: setNameTest(&booleanExpression{
  1663. Left: &term{
  1664. Left: &booleanValue{
  1665. Negation: ottltest.Strp("not"),
  1666. SubExpr: &booleanExpression{
  1667. Left: &term{
  1668. Left: &booleanValue{
  1669. ConstExpr: &constExpr{
  1670. Boolean: booleanp(true),
  1671. },
  1672. },
  1673. },
  1674. Right: []*opOrTerm{
  1675. {
  1676. Operator: "or",
  1677. Term: &term{
  1678. Left: &booleanValue{
  1679. ConstExpr: &constExpr{
  1680. Boolean: booleanp(false),
  1681. },
  1682. },
  1683. },
  1684. },
  1685. },
  1686. },
  1687. },
  1688. },
  1689. }),
  1690. },
  1691. {
  1692. statement: `True()`,
  1693. expected: setNameTest(&booleanExpression{
  1694. Left: &term{
  1695. Left: &booleanValue{
  1696. ConstExpr: &constExpr{
  1697. Converter: &converter{
  1698. Function: "True",
  1699. },
  1700. },
  1701. },
  1702. },
  1703. }),
  1704. },
  1705. {
  1706. statement: `True() and False()`,
  1707. expected: setNameTest(&booleanExpression{
  1708. Left: &term{
  1709. Left: &booleanValue{
  1710. ConstExpr: &constExpr{
  1711. Converter: &converter{
  1712. Function: "True",
  1713. },
  1714. },
  1715. },
  1716. Right: []*opAndBooleanValue{
  1717. {
  1718. Operator: "and",
  1719. Value: &booleanValue{
  1720. ConstExpr: &constExpr{
  1721. Converter: &converter{
  1722. Function: "False",
  1723. },
  1724. },
  1725. },
  1726. },
  1727. },
  1728. },
  1729. }),
  1730. },
  1731. }
  1732. // create a test name that doesn't confuse vscode so we can rerun tests with one click
  1733. pat := regexp.MustCompile("[^a-zA-Z0-9]+")
  1734. for _, tt := range tests {
  1735. name := pat.ReplaceAllString(tt.statement, "_")
  1736. t.Run(name, func(t *testing.T) {
  1737. statement := `set(name, "test") where ` + tt.statement
  1738. parsed, err := parseStatement(statement)
  1739. assert.NoError(t, err)
  1740. assert.Equal(t, tt.expected, parsed)
  1741. })
  1742. }
  1743. }
  1744. var testSymbolTable = map[EnumSymbol]Enum{
  1745. "TEST_ENUM": 0,
  1746. "TEST_ENUM_ONE": 1,
  1747. "TEST_ENUM_TWO": 2,
  1748. }
  1749. func testParseEnum(val *EnumSymbol) (*Enum, error) {
  1750. if val != nil {
  1751. if enum, ok := testSymbolTable[*val]; ok {
  1752. return &enum, nil
  1753. }
  1754. return nil, fmt.Errorf("enum symbol not found")
  1755. }
  1756. return nil, fmt.Errorf("enum symbol not provided")
  1757. }
  1758. func Test_ParseStatements_Error(t *testing.T) {
  1759. statements := []string{
  1760. `set(`,
  1761. `set("foo)`,
  1762. `set(name.)`,
  1763. }
  1764. p, _ := NewParser(
  1765. CreateFactoryMap[any](),
  1766. testParsePath,
  1767. componenttest.NewNopTelemetrySettings(),
  1768. WithEnumParser[any](testParseEnum),
  1769. )
  1770. _, err := p.ParseStatements(statements)
  1771. assert.Error(t, err)
  1772. var e interface{ Unwrap() []error }
  1773. if errors.As(err, &e) {
  1774. uw := e.Unwrap()
  1775. assert.Len(t, uw, len(statements), "ParseStatements didn't return an error per statement")
  1776. for i, statementErr := range uw {
  1777. assert.ErrorContains(t, statementErr, fmt.Sprintf("unable to parse OTTL statement %q", statements[i]))
  1778. }
  1779. } else {
  1780. assert.Fail(t, "ParseStatements didn't return an error per statement")
  1781. }
  1782. }
  1783. func Test_ParseConditions_Error(t *testing.T) {
  1784. conditions := []string{
  1785. `True(`,
  1786. `"foo == "foo"`,
  1787. `set()`,
  1788. }
  1789. p, _ := NewParser(
  1790. CreateFactoryMap[any](),
  1791. testParsePath,
  1792. componenttest.NewNopTelemetrySettings(),
  1793. WithEnumParser[any](testParseEnum),
  1794. )
  1795. _, err := p.ParseConditions(conditions)
  1796. assert.Error(t, err)
  1797. var e interface{ Unwrap() []error }
  1798. if errors.As(err, &e) {
  1799. uw := e.Unwrap()
  1800. assert.Len(t, uw, len(conditions), "ParseConditions didn't return an error per condition")
  1801. for i, conditionErr := range uw {
  1802. assert.ErrorContains(t, conditionErr, fmt.Sprintf("unable to parse OTTL condition %q", conditions[i]))
  1803. }
  1804. } else {
  1805. assert.Fail(t, "ParseConditions didn't return an error per condition")
  1806. }
  1807. }
  1808. // This test doesn't validate parser results, simply checks whether the parse succeeds or not.
  1809. // It's a fast way to check a large range of possible syntaxes.
  1810. func Test_parseStatement(t *testing.T) {
  1811. tests := []struct {
  1812. statement string
  1813. wantErr bool
  1814. }{
  1815. {`set(`, true},
  1816. {`set("foo)`, true},
  1817. {`set(name.)`, true},
  1818. {`("foo")`, true},
  1819. {`set("foo") where name =||= "fido"`, true},
  1820. {`set(span_id, SpanIDWrapper{not a hex string})`, true},
  1821. {`set(span_id, SpanIDWrapper{01})`, true},
  1822. {`set(span_id, SpanIDWrapper{010203040506070809})`, true},
  1823. {`set(trace_id, TraceIDWrapper{not a hex string})`, true},
  1824. {`set(trace_id, TraceIDWrapper{0102030405060708090a0b0c0d0e0f})`, true},
  1825. {`set(trace_id, TraceIDWrapper{0102030405060708090a0b0c0d0e0f1011})`, true},
  1826. {`set("foo") where name = "fido"`, true},
  1827. {`set("foo") where name or "fido"`, true},
  1828. {`set("foo") where name and "fido"`, true},
  1829. {`set("foo") where name and`, true},
  1830. {`set("foo") where name or`, true},
  1831. {`set("foo") where (`, true},
  1832. {`set("foo") where )`, true},
  1833. {`set("foo") where (name == "fido"))`, true},
  1834. {`set("foo") where ((name == "fido")`, true},
  1835. {`Set()`, true},
  1836. {`set(int())`, true},
  1837. {`set(1 + int())`, true},
  1838. {`set(int() + 1)`, true},
  1839. {`set(1 * int())`, true},
  1840. {`set(1 * 1 + (2 * int()))`, true},
  1841. {`set() where int() == 1`, true},
  1842. {`set() where 1 == int()`, true},
  1843. {`set() where true and 1 == int() `, true},
  1844. {`set() where false or 1 == int() `, true},
  1845. {`set(foo.attributes["bar"].cat, "dog")`, false},
  1846. {`set(set = foo.attributes["animal"], val = "dog") where animal == "cat"`, false},
  1847. {`test() where service == "pinger" or foo.attributes["endpoint"] == "/x/alive"`, false},
  1848. {`test() where service == "pinger" or foo.attributes["verb"] == "GET" and foo.attributes["endpoint"] == "/x/alive"`, false},
  1849. {`test() where animal > "cat"`, false},
  1850. {`test() where animal >= "cat"`, false},
  1851. {`test() where animal <= "cat"`, false},
  1852. {`test() where animal < "cat"`, false},
  1853. {`test() where animal =< "dog"`, true},
  1854. {`test() where animal => "dog"`, true},
  1855. {`test() where animal <> "dog"`, true},
  1856. {`test() where animal = "dog"`, true},
  1857. {`test() where animal`, true},
  1858. {`test() where animal ==`, true},
  1859. {`test() where ==`, true},
  1860. {`test() where == animal`, true},
  1861. {`test() where attributes["path"] == "/healthcheck"`, false},
  1862. {`test() where one() == 1`, true},
  1863. {`test(fail())`, true},
  1864. {`Test()`, true},
  1865. }
  1866. pat := regexp.MustCompile("[^a-zA-Z0-9]+")
  1867. for _, tt := range tests {
  1868. name := pat.ReplaceAllString(tt.statement, "_")
  1869. t.Run(name, func(t *testing.T) {
  1870. ast, err := parseStatement(tt.statement)
  1871. if (err != nil) != tt.wantErr {
  1872. t.Errorf("parseStatement(%s) error = %v, wantErr %v", tt.statement, err, tt.wantErr)
  1873. t.Errorf("AST: %+v", ast)
  1874. return
  1875. }
  1876. })
  1877. }
  1878. }
  1879. // This test doesn't validate parser results, simply checks whether the parse succeeds or not.
  1880. // It's a fast way to check a large range of possible syntaxes.
  1881. func Test_parseCondition(t *testing.T) {
  1882. tests := []struct {
  1883. condition string
  1884. wantErr bool
  1885. }{
  1886. {`set(`, true},
  1887. {`set("foo)`, true},
  1888. {`set(name.)`, true},
  1889. {`("foo")`, true},
  1890. {`name =||= "fido"`, true},
  1891. {`name = "fido"`, true},
  1892. {`name or "fido"`, true},
  1893. {`name and "fido"`, true},
  1894. {`name and`, true},
  1895. {`name or`, true},
  1896. {`(`, true},
  1897. {`)`, true},
  1898. {`(name == "fido"))`, true},
  1899. {`((name == "fido")`, true},
  1900. {`set()`, true},
  1901. {`Int() == 1`, false},
  1902. {`1 == Int()`, false},
  1903. {`true and 1 == Int() `, false},
  1904. {`false or 1 == Int() `, false},
  1905. {`service == "pinger" or foo.attributes["endpoint"] == "/x/alive"`, false},
  1906. {`service == "pinger" or foo.attributes["verb"] == "GET" and foo.attributes["endpoint"] == "/x/alive"`, false},
  1907. {`animal > "cat"`, false},
  1908. {`animal >= "cat"`, false},
  1909. {`animal <= "cat"`, false},
  1910. {`animal < "cat"`, false},
  1911. {`animal =< "dog"`, true},
  1912. {`animal => "dog"`, true},
  1913. {`animal <> "dog"`, true},
  1914. {`animal = "dog"`, true},
  1915. {`animal`, true},
  1916. {`animal ==`, true},
  1917. {`==`, true},
  1918. {`== animal`, true},
  1919. {`attributes["path"] == "/healthcheck"`, false},
  1920. {`One() == 1`, false},
  1921. {`test(fail())`, true},
  1922. {`Test()`, false},
  1923. }
  1924. pat := regexp.MustCompile("[^a-zA-Z0-9]+")
  1925. for _, tt := range tests {
  1926. name := pat.ReplaceAllString(tt.condition, "_")
  1927. t.Run(name, func(t *testing.T) {
  1928. ast, err := parseCondition(tt.condition)
  1929. if (err != nil) != tt.wantErr {
  1930. t.Errorf("parseCondition(%s) error = %v, wantErr %v", tt.condition, err, tt.wantErr)
  1931. t.Errorf("AST: %+v", ast)
  1932. return
  1933. }
  1934. })
  1935. }
  1936. }
  1937. func Test_Statement_Execute(t *testing.T) {
  1938. tests := []struct {
  1939. name string
  1940. condition boolExpressionEvaluator[any]
  1941. function ExprFunc[any]
  1942. expectedCondition bool
  1943. expectedResult any
  1944. }{
  1945. {
  1946. name: "Condition matched",
  1947. condition: alwaysTrue[any],
  1948. function: func(ctx context.Context, tCtx any) (any, error) {
  1949. return 1, nil
  1950. },
  1951. expectedCondition: true,
  1952. expectedResult: 1,
  1953. },
  1954. {
  1955. name: "Condition not matched",
  1956. condition: alwaysFalse[any],
  1957. function: func(ctx context.Context, tCtx any) (any, error) {
  1958. return 1, nil
  1959. },
  1960. expectedCondition: false,
  1961. expectedResult: nil,
  1962. },
  1963. {
  1964. name: "No result",
  1965. condition: alwaysTrue[any],
  1966. function: func(ctx context.Context, tCtx any) (any, error) {
  1967. return nil, nil
  1968. },
  1969. expectedCondition: true,
  1970. expectedResult: nil,
  1971. },
  1972. }
  1973. for _, tt := range tests {
  1974. t.Run(tt.name, func(t *testing.T) {
  1975. statement := Statement[any]{
  1976. condition: BoolExpr[any]{tt.condition},
  1977. function: Expr[any]{exprFunc: tt.function},
  1978. }
  1979. result, condition, err := statement.Execute(context.Background(), nil)
  1980. assert.NoError(t, err)
  1981. assert.Equal(t, tt.expectedCondition, condition)
  1982. assert.Equal(t, tt.expectedResult, result)
  1983. })
  1984. }
  1985. }
  1986. func Test_Condition_Eval(t *testing.T) {
  1987. tests := []struct {
  1988. name string
  1989. condition boolExpressionEvaluator[any]
  1990. expectedResult bool
  1991. }{
  1992. {
  1993. name: "Condition matched",
  1994. condition: alwaysTrue[any],
  1995. expectedResult: true,
  1996. },
  1997. {
  1998. name: "Condition not matched",
  1999. condition: alwaysFalse[any],
  2000. expectedResult: false,
  2001. },
  2002. }
  2003. for _, tt := range tests {
  2004. t.Run(tt.name, func(t *testing.T) {
  2005. condition := Condition[any]{
  2006. condition: BoolExpr[any]{tt.condition},
  2007. }
  2008. result, err := condition.Eval(context.Background(), nil)
  2009. assert.NoError(t, err)
  2010. assert.Equal(t, tt.expectedResult, result)
  2011. })
  2012. }
  2013. }
  2014. func Test_Statements_Execute_Error(t *testing.T) {
  2015. tests := []struct {
  2016. name string
  2017. condition boolExpressionEvaluator[any]
  2018. function ExprFunc[any]
  2019. errorMode ErrorMode
  2020. }{
  2021. {
  2022. name: "IgnoreError error from condition",
  2023. condition: func(context.Context, any) (bool, error) {
  2024. return true, fmt.Errorf("test")
  2025. },
  2026. function: func(ctx context.Context, tCtx any) (any, error) {
  2027. return 1, nil
  2028. },
  2029. errorMode: IgnoreError,
  2030. },
  2031. {
  2032. name: "PropagateError error from condition",
  2033. condition: func(context.Context, any) (bool, error) {
  2034. return true, fmt.Errorf("test")
  2035. },
  2036. function: func(ctx context.Context, tCtx any) (any, error) {
  2037. return 1, nil
  2038. },
  2039. errorMode: PropagateError,
  2040. },
  2041. {
  2042. name: "IgnoreError error from function",
  2043. condition: func(context.Context, any) (bool, error) {
  2044. return true, nil
  2045. },
  2046. function: func(ctx context.Context, tCtx any) (any, error) {
  2047. return 1, fmt.Errorf("test")
  2048. },
  2049. errorMode: IgnoreError,
  2050. },
  2051. {
  2052. name: "PropagateError error from function",
  2053. condition: func(context.Context, any) (bool, error) {
  2054. return true, nil
  2055. },
  2056. function: func(ctx context.Context, tCtx any) (any, error) {
  2057. return 1, fmt.Errorf("test")
  2058. },
  2059. errorMode: PropagateError,
  2060. },
  2061. }
  2062. for _, tt := range tests {
  2063. t.Run(tt.name, func(t *testing.T) {
  2064. statements := Statements[any]{
  2065. statements: []*Statement[any]{
  2066. {
  2067. condition: BoolExpr[any]{tt.condition},
  2068. function: Expr[any]{exprFunc: tt.function},
  2069. },
  2070. },
  2071. errorMode: tt.errorMode,
  2072. telemetrySettings: componenttest.NewNopTelemetrySettings(),
  2073. }
  2074. err := statements.Execute(context.Background(), nil)
  2075. if tt.errorMode == PropagateError {
  2076. assert.Error(t, err)
  2077. } else {
  2078. assert.NoError(t, err)
  2079. }
  2080. })
  2081. }
  2082. }
  2083. func Test_Statements_Eval(t *testing.T) {
  2084. tests := []struct {
  2085. name string
  2086. conditions []boolExpressionEvaluator[any]
  2087. function ExprFunc[any]
  2088. errorMode ErrorMode
  2089. expectedResult bool
  2090. }{
  2091. {
  2092. name: "True",
  2093. conditions: []boolExpressionEvaluator[any]{
  2094. alwaysTrue[any],
  2095. },
  2096. errorMode: IgnoreError,
  2097. expectedResult: true,
  2098. },
  2099. {
  2100. name: "At least one True",
  2101. conditions: []boolExpressionEvaluator[any]{
  2102. alwaysFalse[any],
  2103. alwaysFalse[any],
  2104. alwaysTrue[any],
  2105. },
  2106. errorMode: IgnoreError,
  2107. expectedResult: true,
  2108. },
  2109. {
  2110. name: "False",
  2111. conditions: []boolExpressionEvaluator[any]{
  2112. alwaysFalse[any],
  2113. alwaysFalse[any],
  2114. },
  2115. errorMode: IgnoreError,
  2116. expectedResult: false,
  2117. },
  2118. {
  2119. name: "Error is false when using Ignore",
  2120. conditions: []boolExpressionEvaluator[any]{
  2121. alwaysFalse[any],
  2122. func(context.Context, any) (bool, error) {
  2123. return true, fmt.Errorf("test")
  2124. },
  2125. alwaysTrue[any],
  2126. },
  2127. errorMode: IgnoreError,
  2128. expectedResult: true,
  2129. },
  2130. }
  2131. for _, tt := range tests {
  2132. t.Run(tt.name, func(t *testing.T) {
  2133. var rawStatements []*Statement[any]
  2134. for _, condition := range tt.conditions {
  2135. rawStatements = append(rawStatements, &Statement[any]{
  2136. condition: BoolExpr[any]{condition},
  2137. function: Expr[any]{
  2138. exprFunc: func(ctx context.Context, tCtx any) (any, error) {
  2139. return nil, fmt.Errorf("function should not be called")
  2140. },
  2141. },
  2142. })
  2143. }
  2144. statements := Statements[any]{
  2145. statements: rawStatements,
  2146. telemetrySettings: componenttest.NewNopTelemetrySettings(),
  2147. errorMode: tt.errorMode,
  2148. }
  2149. result, err := statements.Eval(context.Background(), nil)
  2150. assert.NoError(t, err)
  2151. assert.Equal(t, tt.expectedResult, result)
  2152. })
  2153. }
  2154. }
  2155. func Test_Statements_Eval_Error(t *testing.T) {
  2156. tests := []struct {
  2157. name string
  2158. conditions []boolExpressionEvaluator[any]
  2159. function ExprFunc[any]
  2160. errorMode ErrorMode
  2161. }{
  2162. {
  2163. name: "Propagate Error from function",
  2164. conditions: []boolExpressionEvaluator[any]{
  2165. func(context.Context, any) (bool, error) {
  2166. return true, fmt.Errorf("test")
  2167. },
  2168. },
  2169. errorMode: PropagateError,
  2170. },
  2171. }
  2172. for _, tt := range tests {
  2173. t.Run(tt.name, func(t *testing.T) {
  2174. var rawStatements []*Statement[any]
  2175. for _, condition := range tt.conditions {
  2176. rawStatements = append(rawStatements, &Statement[any]{
  2177. condition: BoolExpr[any]{condition},
  2178. function: Expr[any]{
  2179. exprFunc: func(ctx context.Context, tCtx any) (any, error) {
  2180. return nil, fmt.Errorf("function should not be called")
  2181. },
  2182. },
  2183. })
  2184. }
  2185. statements := Statements[any]{
  2186. statements: rawStatements,
  2187. telemetrySettings: componenttest.NewNopTelemetrySettings(),
  2188. errorMode: tt.errorMode,
  2189. }
  2190. result, err := statements.Eval(context.Background(), nil)
  2191. assert.Error(t, err)
  2192. assert.False(t, result)
  2193. })
  2194. }
  2195. }