func_test.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * EliasDB
  3. *
  4. * Copyright 2016 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the Mozilla Public
  7. * License, v. 2.0. If a copy of the MPL was not distributed with this
  8. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. */
  10. package interpreter
  11. import "testing"
  12. func TestDateFunctions(t *testing.T) {
  13. gm, _ := dateGraph()
  14. rt := NewGetRuntimeProvider("test", "main", gm, NewDefaultNodeInfo(gm))
  15. if _, err := getResult("get datetest", `
  16. Labels: Datetest Key, Rfc3339 Value, Naive Value, Datetest Name, Unix
  17. Format: auto, auto, auto, auto, auto
  18. Data: 1:n:key, 1:n:RFC3339_value, 1:n:naive_value, 1:n:name, 1:n:unix
  19. 000, 2012-10-09T19:00:55Z, 2012-10-09, date1, 1349809255
  20. 001, 2012-10-12T19:00:55+02:00, 2012-10-12, date2, 1350061255
  21. `[1:], rt, true); err != nil {
  22. t.Error(err)
  23. return
  24. }
  25. // Test default conversion to RFC3339
  26. if _, err := getResult("get datetest where @parseDate(RFC3339_value) = unix", `
  27. Labels: Datetest Key, Rfc3339 Value, Naive Value, Datetest Name, Unix
  28. Format: auto, auto, auto, auto, auto
  29. Data: 1:n:key, 1:n:RFC3339_value, 1:n:naive_value, 1:n:name, 1:n:unix
  30. 000, 2012-10-09T19:00:55Z, 2012-10-09, date1, 1349809255
  31. 001, 2012-10-12T19:00:55+02:00, 2012-10-12, date2, 1350061255
  32. `[1:], rt, true); err != nil {
  33. t.Error(err)
  34. return
  35. }
  36. // The format string '2006-01-02' interprets <year>-<month>-<day>
  37. // The string 2012-10-12 is interpreted as 2012-10-12 00:00:00 +0000 UTC
  38. if _, err := getResult("get datetest where @parseDate(naive_value, '2006-01-02') > @parseDate('2012-10-11', '2006-01-02')", `
  39. Labels: Datetest Key, Rfc3339 Value, Naive Value, Datetest Name, Unix
  40. Format: auto, auto, auto, auto, auto
  41. Data: 1:n:key, 1:n:RFC3339_value, 1:n:naive_value, 1:n:name, 1:n:unix
  42. 001, 2012-10-12T19:00:55+02:00, 2012-10-12, date2, 1350061255
  43. `[1:], rt, true); err != nil {
  44. t.Error(err)
  45. return
  46. }
  47. }
  48. func TestCountFunctions(t *testing.T) {
  49. gm, _ := songGraphGroups()
  50. rt := NewGetRuntimeProvider("test", "main", gm, NewDefaultNodeInfo(gm))
  51. rt2 := NewLookupRuntimeProvider("test", "main", gm, NewDefaultNodeInfo(gm))
  52. if _, err := getResult("get Author traverse :::Song end show name, 2:n:name", `
  53. Labels: Author Name, Name
  54. Format: auto, auto
  55. Data: 1:n:name, 2:n:name
  56. Hans, MyOnlySong3
  57. John, Aria1
  58. John, Aria2
  59. John, Aria3
  60. John, Aria4
  61. Mike, DeadSong2
  62. Mike, FightSong4
  63. Mike, LoveSong3
  64. Mike, StrangeSong1
  65. `[1:], rt, true); err != nil {
  66. t.Error(err)
  67. return
  68. }
  69. if _, err := getResult("get Author show name, @count(1, :::Song) AS mycount format xxx", `
  70. Labels: Author Name, mycount
  71. Format: auto, xxx
  72. Data: 1:n:name, 1:func:count()
  73. Hans, 1
  74. John, 4
  75. Mike, 4
  76. `[1:], rt, true); err != nil {
  77. t.Error(err)
  78. return
  79. }
  80. if _, err := getResult("get group traverse ::: end show key, @count(2, :::Author)", `
  81. Labels: Group Key, Count
  82. Format: auto, auto
  83. Data: 1:n:key, 2:func:count()
  84. Best, 1
  85. Best, 1
  86. Best, 1
  87. Best, 1
  88. `[1:], rt, true); err != nil {
  89. t.Error(err)
  90. return
  91. }
  92. if _, err := getResult("get Author traverse :::Song where (name beginswith 'A') or name beginswith 'L' end show key, name, 2:n:name", `
  93. Labels: Author Key, Author Name, Name
  94. Format: auto, auto, auto
  95. Data: 1:n:key, 1:n:name, 2:n:name
  96. 000, John, Aria1
  97. 000, John, Aria2
  98. 000, John, Aria3
  99. 000, John, Aria4
  100. 123, Mike, LoveSong3
  101. `[1:], rt, true); err != nil {
  102. t.Error(err)
  103. return
  104. }
  105. // Make sure for the source of the count in row 2 (John, 4) is:
  106. // q:lookup Author "000" traverse :::Song where name beginswith A or name beginswith L end show 2:n:key, 2:n:kind, 2:n:name
  107. if res, err := getResult("get Author show name, @count(1, :::Song, r\"(name beginswith A) or name beginswith 'L' TRAVERSE ::: END\") AS mycount format xxx", `
  108. Labels: Author Name, mycount
  109. Format: auto, xxx
  110. Data: 1:n:name, 1:func:count()
  111. Hans, 0
  112. John, 4
  113. Mike, 1
  114. `[1:], rt, true); err != nil || res.RowSource(1)[1] != `q:lookup Author "000" traverse :::Song where name beginswith A or name beginswith L end show 2:n:key, 2:n:kind, 2:n:name` {
  115. t.Error(res.RowSource(1)[1], err)
  116. return
  117. }
  118. // Make sure the source query has the expected result (the source nodes for the count of 4)
  119. if _, err := getResult(`lookup Author "000" traverse :::Song where name beginswith A or name beginswith L end show 2:n:key, 2:n:kind, 2:n:name`, `
  120. Labels: Key, Kind, Name
  121. Format: auto, auto, auto
  122. Data: 2:n:key, 2:n:kind, 2:n:name
  123. Aria1, Song, Aria1
  124. Aria2, Song, Aria2
  125. Aria3, Song, Aria3
  126. Aria4, Song, Aria4
  127. `[1:], rt2, true); err != nil {
  128. t.Error(err)
  129. return
  130. }
  131. // Use the count feature in the where clause - get all authors who have only one song beginning with M or L
  132. if _, err := getResult("get Author where @count(:::Song, \"(name beginswith 'M') or name beginswith 'L'\") = 1 show key, name, @count(1, :::Song, \"(name beginswith 'M') or name beginswith 'L'\")", `
  133. Labels: Author Key, Author Name, Count
  134. Format: auto, auto, auto
  135. Data: 1:n:key, 1:n:name, 1:func:count()
  136. 123, Mike, 1
  137. 456, Hans, 1
  138. `[1:], rt, true); err != nil {
  139. t.Error(err)
  140. return
  141. }
  142. }
  143. func TestFunctionErrors(t *testing.T) {
  144. gm, _ := songGraphGroups()
  145. rt := NewGetRuntimeProvider("test", "main", gm, NewDefaultNodeInfo(gm))
  146. // Test parsing and runtime error
  147. if _, err := getResult("get group show key, @unknownfunction(:::Author)", "", rt, true); err.Error() !=
  148. "EQL error in test: Invalid construct (Unknown function: unknownfunction) (Line:1 Pos:21)" {
  149. t.Error(err)
  150. return
  151. }
  152. if _, err := getResult("get group show key, @count(:::Author)", "", rt, true); err.Error() !=
  153. "EQL error in test: Invalid construct (Count function requires 2 or 3 parameters: traversal step, traversal spec, condition clause) (Line:1 Pos:21)" {
  154. t.Error(err)
  155. return
  156. }
  157. if _, err := getResult("get group show key, @count(1, ::Author)", "", rt, true); err.Error() !=
  158. "GraphError: Invalid data (Invalid spec: ::Author)" {
  159. t.Error(err)
  160. return
  161. }
  162. if _, err := getResult("get group show key, @count(99, ::Author)", "", rt, true); err.Error() !=
  163. "EQL error in test: Invalid column data spec (Data index out of range: 99) (Line:1 Pos:21)" {
  164. t.Error(err)
  165. return
  166. }
  167. if _, err := getResult("get Author where @count(:::Song) > 3 show name, @count(1, :::Song)", `
  168. Labels: Author Name, Count
  169. Format: auto, auto
  170. Data: 1:n:name, 1:func:count()
  171. John, 4
  172. Mike, 4
  173. `[1:], rt, true); err != nil {
  174. t.Error(err)
  175. return
  176. }
  177. // Test parsing and runtime error
  178. if _, err := getResult("get Author where @unknownfunction() > 3", "", rt, true); err.Error() !=
  179. "EQL error in test: Invalid construct (Unknown function: unknownfunction) (Line:1 Pos:18)" {
  180. t.Error(err)
  181. return
  182. }
  183. if _, err := getResult("get Author where @count() > 3", "", rt, true); err.Error() !=
  184. "EQL error in test: Invalid construct (Count function requires 1 or 2 parameters: traversal spec, condition clause) (Line:1 Pos:18)" {
  185. t.Error(err)
  186. return
  187. }
  188. if _, err := getResult("get Author where @count(::Song) > 3", "", rt, true); err.Error() !=
  189. "GraphError: Invalid data (Invalid spec: ::Song)" {
  190. t.Error(err)
  191. return
  192. }
  193. if _, err := getResult("get Author show @objget(1)", "", rt, true); err.Error() !=
  194. "EQL error in test: Invalid construct (Objget function requires 3 parameters: traversal step, attribute name, path to value) (Line:1 Pos:17)" {
  195. t.Error(err)
  196. return
  197. }
  198. if _, err := getResult("get Author where @parseDate()", "", rt, true); err.Error() !=
  199. "EQL error in test: Invalid construct (parseDate function requires 1 parameter: date string) (Line:1 Pos:18)" {
  200. t.Error(err)
  201. return
  202. }
  203. if _, err := getResult("get Author where @count(:::Song, \"name\")", "", rt, true); err == nil || err.Error() !=
  204. "EQL error in test: Invalid construct (Could not evaluate condition clause in count function) (Line:1 Pos:18)" {
  205. t.Error(err)
  206. return
  207. }
  208. if _, err := getResult("get Author where @count(:::Song, \"name =\")", "", rt, true); err == nil || err.Error() !=
  209. "EQL error in test: Invalid construct (Invalid condition clause in count function: Parse error in count condition: Unexpected end) (Line:1 Pos:18)" {
  210. t.Error(err)
  211. return
  212. }
  213. if _, err := getResult("get Author where @count(:::Song, \"show\") = 1", "", rt, true); err == nil || err.Error() !=
  214. "EQL error in test: Invalid construct (Invalid condition clause in count function: EQL error in test: Invalid construct (show) (Line:1 Pos:13)) (Line:1 Pos:18)" {
  215. t.Error(err)
  216. return
  217. }
  218. if _, err := getResult("get Author show @count(1, :::Song, \"name\")", "", rt, true); err == nil || err.Error() !=
  219. "EQL error in test: Invalid construct (Could not evaluate condition clause in count function) (Line:1 Pos:17)" {
  220. t.Error(err)
  221. return
  222. }
  223. if _, err := getResult("get Author show @count(1, :::Song, \"name =\")", "", rt, true); err == nil || err.Error() !=
  224. "EQL error in test: Invalid construct (Invalid condition clause in count function: Parse error in count condition: Unexpected end) (Line:1 Pos:17)" {
  225. t.Error(err)
  226. return
  227. }
  228. if _, err := getResult("get Author show @count(1, :::Song, \"show\")", "", rt, true); err == nil || err.Error() !=
  229. "EQL error in test: Invalid construct (show) (Line:1 Pos:13)" {
  230. t.Error(err)
  231. return
  232. }
  233. }