queryresult_test.go 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243
  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 v1
  11. import (
  12. "fmt"
  13. "testing"
  14. "devt.de/krotik/eliasdb/api"
  15. "devt.de/krotik/eliasdb/eql/interpreter"
  16. "devt.de/krotik/eliasdb/graph/data"
  17. )
  18. func TestResultGroupingWithState(t *testing.T) {
  19. queryURL := "http://localhost" + TESTPORT + EndpointQuery
  20. st, header, res := sendTestRequest(queryURL+"/main?q=get+Song+with+ordering(ascending+key)", "GET", nil)
  21. if st != "200 OK" {
  22. t.Error("Unexpected result: ", st, res)
  23. return
  24. }
  25. id := header.Get(HTTPHeaderCacheID)
  26. sr, _ := ResultCache.Get(id)
  27. ssr := sr.(*APISearchResult)
  28. ssr.SetSelection(2, true)
  29. ssr.SetSelection(4, true)
  30. ssr.SetSelection(5, true)
  31. ssr.SetSelection(6, true)
  32. if res := fmt.Sprint(ssr.Selections()); res != "[false false true false true true true false false]" {
  33. t.Error("Unexpected result: ", res)
  34. return
  35. }
  36. queryURL2 := "http://localhost" + TESTPORT + EndpointQueryResult
  37. // Put nodes into a groups
  38. st, _, res = sendTestRequest(queryURL2+id+"/groupselected/g1", "PUT", nil)
  39. if st != "200 OK" || res == "" {
  40. t.Error("Unexpected result: ", st, res)
  41. return
  42. }
  43. ssr.NoneSelection()
  44. ssr.SetSelection(2, true)
  45. ssr.SetSelection(3, true)
  46. st, _, res = sendTestRequest(queryURL2+id+"/groupselected/g2", "PUT", nil)
  47. if st != "200 OK" || res == "" {
  48. t.Error("Unexpected result: ", st, res)
  49. return
  50. }
  51. ssr.SetSelection(4, true)
  52. ssr.SetSelection(5, true)
  53. ssr.SetSelection(6, true)
  54. if res := fmt.Sprint(ssr.Rows()); res != "[[Aria1 Aria1 8] "+
  55. "[Aria2 Aria2 2] "+
  56. "[Aria3 Aria3 4] "+ // Selected - group Best g1 g2
  57. "[Aria4 Aria4 18] "+ // Selected - group g2
  58. "[DeadSong2 DeadSong2 6] "+ // Selected - group g1
  59. "[FightSong4 FightSong4 3] "+ // Selected - group g1
  60. "[LoveSong3 LoveSong3 1] "+ // Selected - group Best g1
  61. "[MyOnlySong3 MyOnlySong3 19] "+
  62. "[StrangeSong1 StrangeSong1 5]]" {
  63. t.Error("Unexpected result: ", res)
  64. return
  65. }
  66. if res := fmt.Sprint(ssr.Selections()); res != "[false false true true true true true false false]" {
  67. t.Error("Unexpected result: ", res)
  68. return
  69. }
  70. // Get information about groups
  71. st, _, gsres := sendTestRequest(queryURL2+id+"/groupselected", "GET", nil)
  72. if st != "200 OK" || gsres != `
  73. {
  74. "groups": [
  75. "Best",
  76. "g1",
  77. "g2"
  78. ],
  79. "keys": [
  80. [
  81. "Aria3",
  82. "LoveSong3"
  83. ],
  84. [
  85. "Aria3",
  86. "DeadSong2",
  87. "FightSong4",
  88. "LoveSong3"
  89. ],
  90. [
  91. "Aria3",
  92. "Aria4"
  93. ]
  94. ],
  95. "kinds": [
  96. [
  97. "Song",
  98. "Song"
  99. ],
  100. [
  101. "Song",
  102. "Song",
  103. "Song",
  104. "Song"
  105. ],
  106. [
  107. "Song",
  108. "Song"
  109. ]
  110. ]
  111. }`[1:] {
  112. t.Error("Unexpected result: ", st, gsres)
  113. return
  114. }
  115. ssr.NoneSelection()
  116. ssr.SetSelection(2, true)
  117. ssr.SetSelection(3, true)
  118. st, _, res = sendTestRequest(queryURL2+id+"/groupselected/g2", "DELETE", nil)
  119. if st != "200 OK" || res == "" {
  120. t.Error("Unexpected result: ", st, res)
  121. return
  122. }
  123. ssr.NoneSelection()
  124. ssr.SetSelection(2, true)
  125. ssr.SetSelection(4, true)
  126. ssr.SetSelection(5, true)
  127. ssr.SetSelection(6, true)
  128. st, _, res = sendTestRequest(queryURL2+id+"/groupselected/g1", "DELETE", nil)
  129. if st != "200 OK" || res == "" {
  130. t.Error("Unexpected result: ", st, res)
  131. return
  132. }
  133. st, _, res = sendTestRequest(queryURL2+id+"/groupselected", "PUT", nil)
  134. if st != "400 Bad Request" || res != "Groupselected can only handle GET and POST requests" {
  135. t.Error("Unexpected result: ", st, res)
  136. return
  137. }
  138. ssr.Header().(*interpreter.SearchHeader).ResPartition = "foo bar"
  139. st, _, res = sendTestRequest(queryURL2+id+"/groupselected", "GET", nil)
  140. if st != "500 Internal Server Error" || res != "GraphError: Invalid data (Partition name foo bar is not alphanumeric - can only contain [a-zA-Z0-9_])" {
  141. t.Error("Unexpected result: ", st, res)
  142. return
  143. }
  144. ssr.Header().(*interpreter.SearchHeader).ResPartition = "main"
  145. st, _, res = sendTestRequest(queryURL2+id+"/groupselected", "GET", nil)
  146. if st != "200 OK" || res != `
  147. {
  148. "groups": [
  149. "Best"
  150. ],
  151. "keys": [
  152. [
  153. "Aria3",
  154. "LoveSong3"
  155. ]
  156. ],
  157. "kinds": [
  158. [
  159. "Song",
  160. "Song"
  161. ]
  162. ]
  163. }`[1:] {
  164. t.Error("Unexpected result: ", st, res)
  165. return
  166. }
  167. n, _, err := api.GM.TraverseMulti("main", "Aria3", "Song", ":::group", true)
  168. data.NodeSort(n)
  169. if err != nil || fmt.Sprint(n) != `[GraphNode:
  170. key : Best
  171. kind : group
  172. ]` {
  173. t.Error(n, err)
  174. return
  175. }
  176. st, _, res = sendTestRequest(queryURL2+id+"/groupselected", "POST", []byte(gsres))
  177. if st != "200 OK" || res == "" {
  178. t.Error("Unexpected result: ", st, res)
  179. return
  180. }
  181. n, _, err = api.GM.TraverseMulti("main", "Aria3", "Song", ":::group", true)
  182. data.NodeSort(n)
  183. if err != nil || fmt.Sprint(n) != `
  184. [GraphNode:
  185. key : Best
  186. kind : group
  187. GraphNode:
  188. key : g1
  189. kind : group
  190. GraphNode:
  191. key : g2
  192. kind : group
  193. ]`[1:] {
  194. t.Error(n, err)
  195. return
  196. }
  197. ssr.SetSelection(3, true) // Make sure also item 3 is selected
  198. st, _, gsres = sendTestRequest(queryURL2+id+"/groupselected", "GET", nil)
  199. if st != "200 OK" || gsres != `
  200. {
  201. "groups": [
  202. "Best",
  203. "g1",
  204. "g2"
  205. ],
  206. "keys": [
  207. [
  208. "Aria3",
  209. "LoveSong3"
  210. ],
  211. [
  212. "Aria3",
  213. "DeadSong2",
  214. "FightSong4",
  215. "LoveSong3"
  216. ],
  217. [
  218. "Aria3",
  219. "Aria4"
  220. ]
  221. ],
  222. "kinds": [
  223. [
  224. "Song",
  225. "Song"
  226. ],
  227. [
  228. "Song",
  229. "Song",
  230. "Song",
  231. "Song"
  232. ],
  233. [
  234. "Song",
  235. "Song"
  236. ]
  237. ]
  238. }`[1:] {
  239. t.Error("Unexpected result: ", st, gsres)
  240. return
  241. }
  242. st, _, res = sendTestRequest(queryURL2+id+"/groupselected", "POST", []byte("{:"))
  243. if st != "400 Bad Request" || res != "Could not decode request body as object with lists of groups, keys and kinds: invalid character ':' looking for beginning of object key string" {
  244. t.Error("Unexpected result: ", st, res)
  245. return
  246. }
  247. st, _, res = sendTestRequest(queryURL2+id+"/groupselected", "POST", []byte(`{"foo":"bar"}`))
  248. if st != "400 Bad Request" || res != "Wrong data structures in request body - expecting an object with lists of groups, keys and kinds." {
  249. t.Error("Unexpected result: ", st, res)
  250. return
  251. }
  252. sstate := `
  253. {
  254. "groups": [
  255. "Best"
  256. ],
  257. "keys": [
  258. [
  259. "Aria3",
  260. "LoveSong3"
  261. ]
  262. ],
  263. "kinds": [
  264. [
  265. "Song",
  266. "Song"
  267. ]
  268. ]
  269. }`[1:]
  270. st, _, res = sendTestRequest(queryURL2+id+"/groupselected", "POST", []byte(sstate))
  271. if st != "200 OK" || res != sstate { // Response should be the same state which we have put in!
  272. t.Error("Unexpected result: ", st, res)
  273. return
  274. }
  275. ssr.Header().(*interpreter.SearchHeader).ResPartition = "foo bar"
  276. st, _, res = sendTestRequest(queryURL2+id+"/groupselected", "POST", []byte(sstate))
  277. if st != "500 Internal Server Error" || res != "GraphError: Invalid data (Partition name foo bar is not alphanumeric - can only contain [a-zA-Z0-9_])" {
  278. t.Error("Unexpected result: ", st, res)
  279. return
  280. }
  281. ssr.Header().(*interpreter.SearchHeader).ResPartition = "main"
  282. // Check the state has been restored
  283. st, _, gsres = sendTestRequest(queryURL2+id+"/groupselected", "GET", nil)
  284. if st != "200 OK" || gsres != `
  285. {
  286. "groups": [
  287. "Best"
  288. ],
  289. "keys": [
  290. [
  291. "Aria3",
  292. "LoveSong3"
  293. ]
  294. ],
  295. "kinds": [
  296. [
  297. "Song",
  298. "Song"
  299. ]
  300. ]
  301. }`[1:] {
  302. t.Error("Unexpected result: ", st, gsres)
  303. return
  304. }
  305. }
  306. func TestResultGroupingSpecifiedGroup(t *testing.T) {
  307. queryURL := "http://localhost" + TESTPORT + EndpointQuery
  308. st, header, res := sendTestRequest(queryURL+"/main?q=get+Song+with+ordering(ascending+key)", "GET", nil)
  309. if st != "200 OK" {
  310. t.Error("Unexpected result: ", st, res)
  311. return
  312. }
  313. id := header.Get(HTTPHeaderCacheID)
  314. sr, _ := ResultCache.Get(id)
  315. ssr := sr.(*APISearchResult)
  316. ssr.SetSelection(2, true)
  317. if res := fmt.Sprint(ssr.Selections()); res != "[false false true false false false false false false]" {
  318. t.Error("Unexpected result: ", res)
  319. return
  320. }
  321. if fmt.Sprint(ssr.RowSources()[2]) != "[n:Song:Aria3 n:Song:Aria3 n:Song:Aria3]" {
  322. t.Error("Unexpected row source:", ssr.RowSources()[2])
  323. return
  324. }
  325. n, _, err := api.GM.TraverseMulti("main", "Aria3", "Song", ":::group", true)
  326. data.NodeSort(n)
  327. if err != nil || fmt.Sprint(n) != `[GraphNode:
  328. key : Best
  329. kind : group
  330. ]` {
  331. t.Error(n, err)
  332. return
  333. }
  334. queryURL2 := "http://localhost" + TESTPORT + EndpointQueryResult
  335. st, _, res = sendTestRequest(queryURL2+id+"/groupselected/foo", "GET", nil)
  336. if st != "400 Bad Request" || res != "Groupselected for a specific group can only handle PUT and DELETE requests" {
  337. t.Error("Unexpected result: ", st, res)
  338. return
  339. }
  340. st, _, res = sendTestRequest(queryURL2+id+"/groupselected/foo", "PUT", nil)
  341. if st != "200 OK" || res == "" {
  342. t.Error("Unexpected result: ", st, res)
  343. return
  344. }
  345. n, _, err = api.GM.TraverseMulti("main", "Aria3", "Song", ":::group", true)
  346. data.NodeSort(n)
  347. if err != nil || fmt.Sprint(n) != `[GraphNode:
  348. key : Best
  349. kind : group
  350. GraphNode:
  351. key : foo
  352. kind : group
  353. ]` {
  354. t.Error(n, err)
  355. return
  356. }
  357. st, _, res = sendTestRequest(queryURL2+id+"/groupselected/foo", "DELETE", nil)
  358. if st != "200 OK" || res == "" {
  359. t.Error("Unexpected result: ", st, res)
  360. return
  361. }
  362. n, _, err = api.GM.TraverseMulti("main", "Aria3", "Song", ":::group", true)
  363. data.NodeSort(n)
  364. if err != nil || fmt.Sprint(n) != `[GraphNode:
  365. key : Best
  366. kind : group
  367. ]` {
  368. t.Error(n, err)
  369. return
  370. }
  371. ssr.SearchResult.Header().(*interpreter.SearchHeader).ResPrimaryKind = "foo"
  372. st, _, res = sendTestRequest(queryURL2+id+"/groupselected/foo", "DELETE", nil)
  373. if st != "400 Bad Request" || res != "Could not determine key of primary node - query needs a primary expression" {
  374. t.Error("Unexpected result: ", st, res)
  375. return
  376. }
  377. st, _, res = sendTestRequest(queryURL2+id+"/select", "GET", nil)
  378. if st != "400 Bad Request" || res != "Could not determine key of primary node - query needs a primary expression" {
  379. t.Error("Unexpected result: ", st, res)
  380. return
  381. }
  382. }
  383. func TestResultSelection(t *testing.T) {
  384. queryURL := "http://localhost" + TESTPORT + EndpointQuery
  385. st, header, res := sendTestRequest(queryURL+"/main?q=get+Song+with+ordering(ascending+key)&offset=2&limit=3", "GET", nil)
  386. id := header.Get(HTTPHeaderCacheID)
  387. if st != "200 OK" || res != `
  388. {
  389. "header": {
  390. "data": [
  391. "1:n:key",
  392. "1:n:name",
  393. "1:n:ranking"
  394. ],
  395. "format": [
  396. "auto",
  397. "auto",
  398. "auto"
  399. ],
  400. "labels": [
  401. "Song Key",
  402. "Song Name",
  403. "Ranking"
  404. ],
  405. "primary_kind": "Song"
  406. },
  407. "rows": [
  408. [
  409. "Aria3",
  410. "Aria3",
  411. 4
  412. ],
  413. [
  414. "Aria4",
  415. "Aria4",
  416. 18
  417. ],
  418. [
  419. "DeadSong2",
  420. "DeadSong2",
  421. 6
  422. ]
  423. ],
  424. "selections": [
  425. false,
  426. false,
  427. false
  428. ],
  429. "sources": [
  430. [
  431. "n:Song:Aria3",
  432. "n:Song:Aria3",
  433. "n:Song:Aria3"
  434. ],
  435. [
  436. "n:Song:Aria4",
  437. "n:Song:Aria4",
  438. "n:Song:Aria4"
  439. ],
  440. [
  441. "n:Song:DeadSong2",
  442. "n:Song:DeadSong2",
  443. "n:Song:DeadSong2"
  444. ]
  445. ],
  446. "total_selections": 0
  447. }`[1:] {
  448. t.Error("Unexpected response:", st, res)
  449. return
  450. }
  451. queryURL2 := "http://localhost" + TESTPORT + EndpointQueryResult
  452. st, _, res = sendTestRequest(queryURL2+id+"/select/", "PUT", []byte(""))
  453. if st != "400 Bad Request" || res != "Need a selection ('all', 'none', 'invert' or row number)" {
  454. t.Error("Unexpected result: ", st, res)
  455. return
  456. }
  457. // Test CSV output
  458. st, _, res = sendTestRequest(queryURL2+id+"/csv", "PUT", nil)
  459. if st != "400 Bad Request" || res != "Csv can only handle GET requests" {
  460. t.Error("Unexpected result: ", st, res)
  461. return
  462. }
  463. st, _, res = sendTestRequest(queryURL2+id+"/csv", "GET", nil)
  464. if st != "200 OK" || res != `
  465. Song Key,Song Name,Ranking
  466. Aria1,Aria1,8
  467. Aria2,Aria2,2
  468. Aria3,Aria3,4
  469. Aria4,Aria4,18
  470. DeadSong2,DeadSong2,6
  471. FightSong4,FightSong4,3
  472. LoveSong3,LoveSong3,1
  473. MyOnlySong3,MyOnlySong3,19
  474. StrangeSong1,StrangeSong1,5`[1:] {
  475. t.Error("Unexpected result: ", st, res)
  476. return
  477. }
  478. // Test selection
  479. st, _, res = sendTestRequest(queryURL2+id+"/select/all", "PUT", nil)
  480. if st != "200 OK" || res != `{
  481. "total_selections": 9
  482. }` {
  483. t.Error("Unexpected result: ", st, res)
  484. return
  485. }
  486. sr, _ := ResultCache.Get(id)
  487. ssr := sr.(*APISearchResult)
  488. if res := fmt.Sprint(ssr.Selections()); res != "[true true true true true true true true true]" {
  489. t.Error("Unexpected result: ", res)
  490. return
  491. }
  492. st, _, res = sendTestRequest(queryURL2+id+"/select/5", "PUT", nil)
  493. if st != "200 OK" || res != `{
  494. "total_selections": 8
  495. }` {
  496. t.Error("Unexpected result: ", st, res)
  497. return
  498. }
  499. st, _, res = sendTestRequest(queryURL2+id+"/select/0", "PUT", nil)
  500. if st != "200 OK" || res != `{
  501. "total_selections": 7
  502. }` {
  503. t.Error("Unexpected result: ", st, res)
  504. return
  505. }
  506. sr, _ = ResultCache.Get(id)
  507. ssr = sr.(*APISearchResult)
  508. if res := fmt.Sprint(ssr.Selections()); res != "[false true true true true false true true true]" {
  509. t.Error("Unexpected result: ", res)
  510. return
  511. }
  512. st, _, res = sendTestRequest(queryURL2+id+"/select/0", "PUT", nil)
  513. if st != "200 OK" || res != `{
  514. "total_selections": 8
  515. }` {
  516. t.Error("Unexpected result: ", st, res)
  517. return
  518. }
  519. sr, _ = ResultCache.Get(id)
  520. ssr = sr.(*APISearchResult)
  521. if res := fmt.Sprint(ssr.Selections()); res != "[true true true true true false true true true]" {
  522. t.Error("Unexpected result: ", res)
  523. return
  524. }
  525. st, _, res = sendTestRequest(queryURL2+id+"/select/invert", "PUT", nil)
  526. if st != "200 OK" || res != `{
  527. "total_selections": 1
  528. }` {
  529. t.Error("Unexpected result: ", st, res)
  530. return
  531. }
  532. sr, _ = ResultCache.Get(id)
  533. ssr = sr.(*APISearchResult)
  534. if res := fmt.Sprint(ssr.Selections()); res != "[false false false false false true false false false]" {
  535. t.Error("Unexpected result: ", res)
  536. return
  537. }
  538. // Test an error in between
  539. st, _, res = sendTestRequest(queryURL2+id+"/select/invert2", "PUT", nil)
  540. if st != "400 Bad Request" || res != "Invalid selection row number" {
  541. t.Error("Unexpected result: ", st, res)
  542. return
  543. }
  544. st, _, res = sendTestRequest(queryURL2+id+"/select/none", "PUT", nil)
  545. if st != "200 OK" || res != `{
  546. "total_selections": 0
  547. }` {
  548. t.Error("Unexpected result: ", st, res)
  549. return
  550. }
  551. sr, _ = ResultCache.Get(id)
  552. ssr = sr.(*APISearchResult)
  553. if res := fmt.Sprint(ssr.Selections()); res != "[false false false false false false false false false]" {
  554. t.Error("Unexpected result: ", res)
  555. return
  556. }
  557. // Blow away the selection aray and simulate a previous selection
  558. ssr.selections = []bool{true, false}
  559. st, _, res = sendTestRequest(queryURL2+id+"/select/2", "PUT", nil)
  560. if st != "200 OK" || res != `{
  561. "total_selections": 2
  562. }` {
  563. t.Error("Unexpected result: ", st, res)
  564. return
  565. }
  566. // Produce an error
  567. st, _, res = sendTestRequest(queryURL2+id+"/select/2", "DELETE", nil)
  568. if st != "400 Bad Request" || res != "Select can only handle GET and PUT requests" {
  569. t.Error("Unexpected result: ", st, res)
  570. return
  571. }
  572. sr, _ = ResultCache.Get(id)
  573. ssr = sr.(*APISearchResult)
  574. if res := fmt.Sprint(ssr.Selections()); res != "[true false true false false false false false false]" {
  575. t.Error("Unexpected result: ", res)
  576. return
  577. }
  578. st, _, res = sendTestRequest(queryURL2+id+"/select", "GET", nil)
  579. if st != "200 OK" || res != `
  580. {
  581. "keys": [
  582. "Aria1",
  583. "Aria3"
  584. ],
  585. "kinds": [
  586. "Song",
  587. "Song"
  588. ]
  589. }`[1:] {
  590. t.Error("Unexpected result: ", st, res)
  591. return
  592. }
  593. st, _, res = sendTestRequest(queryURL+"/main?rid="+id+"&offset=2&limit=3", "GET", nil)
  594. if st != "200 OK" || res != `
  595. {
  596. "header": {
  597. "data": [
  598. "1:n:key",
  599. "1:n:name",
  600. "1:n:ranking"
  601. ],
  602. "format": [
  603. "auto",
  604. "auto",
  605. "auto"
  606. ],
  607. "labels": [
  608. "Song Key",
  609. "Song Name",
  610. "Ranking"
  611. ],
  612. "primary_kind": "Song"
  613. },
  614. "rows": [
  615. [
  616. "Aria3",
  617. "Aria3",
  618. 4
  619. ],
  620. [
  621. "Aria4",
  622. "Aria4",
  623. 18
  624. ],
  625. [
  626. "DeadSong2",
  627. "DeadSong2",
  628. 6
  629. ]
  630. ],
  631. "selections": [
  632. true,
  633. false,
  634. false
  635. ],
  636. "sources": [
  637. [
  638. "n:Song:Aria3",
  639. "n:Song:Aria3",
  640. "n:Song:Aria3"
  641. ],
  642. [
  643. "n:Song:Aria4",
  644. "n:Song:Aria4",
  645. "n:Song:Aria4"
  646. ],
  647. [
  648. "n:Song:DeadSong2",
  649. "n:Song:DeadSong2",
  650. "n:Song:DeadSong2"
  651. ]
  652. ],
  653. "total_selections": 2
  654. }`[1:] {
  655. t.Error("Unexpected response:", st, res)
  656. return
  657. }
  658. }
  659. func TestResultFiltering(t *testing.T) {
  660. queryURL := "http://localhost" + TESTPORT + EndpointQuery
  661. st, header, res := sendTestRequest(queryURL+"/main?q=get+filtertest+with+ordering(ascending+key)", "GET", nil)
  662. if st != "200 OK" || res != `
  663. {
  664. "header": {
  665. "data": [
  666. "1:n:key",
  667. "1:n:val1",
  668. "1:n:val2",
  669. "1:n:val3"
  670. ],
  671. "format": [
  672. "auto",
  673. "auto",
  674. "auto",
  675. "auto"
  676. ],
  677. "labels": [
  678. "Filtertest Key",
  679. "Val1",
  680. "Val2",
  681. "Val3"
  682. ],
  683. "primary_kind": "filtertest"
  684. },
  685. "rows": [
  686. [
  687. "1",
  688. "test",
  689. "Hans",
  690. "foo"
  691. ],
  692. [
  693. "2",
  694. "test1",
  695. "Hans",
  696. "foo"
  697. ],
  698. [
  699. "3",
  700. "test2",
  701. "Hans",
  702. "foo"
  703. ],
  704. [
  705. "4",
  706. "test3",
  707. "Peter",
  708. "foo"
  709. ],
  710. [
  711. "5",
  712. "test4",
  713. "Peter",
  714. "foo"
  715. ],
  716. [
  717. "6",
  718. "test5",
  719. "Peter",
  720. "foo"
  721. ],
  722. [
  723. "7",
  724. "test6",
  725. "Anna",
  726. "foo"
  727. ],
  728. [
  729. "8",
  730. "test7",
  731. "Anna",
  732. "foo"
  733. ],
  734. [
  735. "9",
  736. "test8",
  737. "Steve",
  738. "foo"
  739. ],
  740. [
  741. "10",
  742. "test9",
  743. "Steve",
  744. "foo"
  745. ],
  746. [
  747. "11",
  748. "test10",
  749. "Franz",
  750. "foo"
  751. ],
  752. [
  753. "12",
  754. "test11",
  755. "Kevin",
  756. "foo"
  757. ],
  758. [
  759. "13",
  760. "test12",
  761. "Kevin",
  762. "foo"
  763. ],
  764. [
  765. "14",
  766. "test13",
  767. "Kevin",
  768. "foo"
  769. ],
  770. [
  771. "15",
  772. "test14",
  773. "X1",
  774. "foo"
  775. ],
  776. [
  777. "16",
  778. "test15",
  779. "X2",
  780. "foo"
  781. ],
  782. [
  783. "17",
  784. "test16",
  785. "X3",
  786. "foo"
  787. ],
  788. [
  789. "18",
  790. "test17",
  791. "X4",
  792. "foo"
  793. ],
  794. [
  795. "19",
  796. "test18",
  797. "X5",
  798. "foo"
  799. ]
  800. ],
  801. "selections": [
  802. false,
  803. false,
  804. false,
  805. false,
  806. false,
  807. false,
  808. false,
  809. false,
  810. false,
  811. false,
  812. false,
  813. false,
  814. false,
  815. false,
  816. false,
  817. false,
  818. false,
  819. false,
  820. false
  821. ],
  822. "sources": [
  823. [
  824. "n:filtertest:1",
  825. "n:filtertest:1",
  826. "n:filtertest:1",
  827. "n:filtertest:1"
  828. ],
  829. [
  830. "n:filtertest:2",
  831. "n:filtertest:2",
  832. "n:filtertest:2",
  833. "n:filtertest:2"
  834. ],
  835. [
  836. "n:filtertest:3",
  837. "n:filtertest:3",
  838. "n:filtertest:3",
  839. "n:filtertest:3"
  840. ],
  841. [
  842. "n:filtertest:4",
  843. "n:filtertest:4",
  844. "n:filtertest:4",
  845. "n:filtertest:4"
  846. ],
  847. [
  848. "n:filtertest:5",
  849. "n:filtertest:5",
  850. "n:filtertest:5",
  851. "n:filtertest:5"
  852. ],
  853. [
  854. "n:filtertest:6",
  855. "n:filtertest:6",
  856. "n:filtertest:6",
  857. "n:filtertest:6"
  858. ],
  859. [
  860. "n:filtertest:7",
  861. "n:filtertest:7",
  862. "n:filtertest:7",
  863. "n:filtertest:7"
  864. ],
  865. [
  866. "n:filtertest:8",
  867. "n:filtertest:8",
  868. "n:filtertest:8",
  869. "n:filtertest:8"
  870. ],
  871. [
  872. "n:filtertest:9",
  873. "n:filtertest:9",
  874. "n:filtertest:9",
  875. "n:filtertest:9"
  876. ],
  877. [
  878. "n:filtertest:10",
  879. "n:filtertest:10",
  880. "n:filtertest:10",
  881. "n:filtertest:10"
  882. ],
  883. [
  884. "n:filtertest:11",
  885. "n:filtertest:11",
  886. "n:filtertest:11",
  887. "n:filtertest:11"
  888. ],
  889. [
  890. "n:filtertest:12",
  891. "n:filtertest:12",
  892. "n:filtertest:12",
  893. "n:filtertest:12"
  894. ],
  895. [
  896. "n:filtertest:13",
  897. "n:filtertest:13",
  898. "n:filtertest:13",
  899. "n:filtertest:13"
  900. ],
  901. [
  902. "n:filtertest:14",
  903. "n:filtertest:14",
  904. "n:filtertest:14",
  905. "n:filtertest:14"
  906. ],
  907. [
  908. "n:filtertest:15",
  909. "n:filtertest:15",
  910. "n:filtertest:15",
  911. "n:filtertest:15"
  912. ],
  913. [
  914. "n:filtertest:16",
  915. "n:filtertest:16",
  916. "n:filtertest:16",
  917. "n:filtertest:16"
  918. ],
  919. [
  920. "n:filtertest:17",
  921. "n:filtertest:17",
  922. "n:filtertest:17",
  923. "n:filtertest:17"
  924. ],
  925. [
  926. "n:filtertest:18",
  927. "n:filtertest:18",
  928. "n:filtertest:18",
  929. "n:filtertest:18"
  930. ],
  931. [
  932. "n:filtertest:19",
  933. "n:filtertest:19",
  934. "n:filtertest:19",
  935. "n:filtertest:19"
  936. ]
  937. ],
  938. "total_selections": 0
  939. }`[1:] {
  940. t.Error("Unexpected response:", st, res)
  941. return
  942. }
  943. queryURL = "http://localhost" + TESTPORT + EndpointQueryResult
  944. id := header.Get(HTTPHeaderCacheID)
  945. st, _, res = sendTestRequest(queryURL+id+"/quickfilter/2?limit=10", "PUT", nil)
  946. if st != "400 Bad Request" || res != "Quickfilter can only handle GET requests" {
  947. t.Error("Unexpected response:", st, res)
  948. return
  949. }
  950. _, _, res = sendTestRequest(queryURL+id+"/quickfilter/2?limit=10", "GET", nil)
  951. // The normal case - some values are the same
  952. if res != `
  953. {
  954. "frequencies": [
  955. 3,
  956. 3,
  957. 3,
  958. 2,
  959. 2,
  960. 1,
  961. 1,
  962. 1,
  963. 1,
  964. 1
  965. ],
  966. "values": [
  967. "Hans",
  968. "Kevin",
  969. "Peter",
  970. "Anna",
  971. "Steve",
  972. "Franz",
  973. "X1",
  974. "X2",
  975. "X3",
  976. "X4"
  977. ]
  978. }`[1:] {
  979. t.Error("Unexpected result: ", res)
  980. return
  981. }
  982. _, _, res = sendTestRequest(queryURL+"/"+id+"/quickfilter/2", "GET", nil)
  983. if res != `
  984. {
  985. "frequencies": [
  986. 3,
  987. 3,
  988. 3,
  989. 2,
  990. 2,
  991. 1,
  992. 1,
  993. 1,
  994. 1,
  995. 1,
  996. 1
  997. ],
  998. "values": [
  999. "Hans",
  1000. "Kevin",
  1001. "Peter",
  1002. "Anna",
  1003. "Steve",
  1004. "Franz",
  1005. "X1",
  1006. "X2",
  1007. "X3",
  1008. "X4",
  1009. "X5"
  1010. ]
  1011. }`[1:] {
  1012. t.Error("Unexpected result: ", res)
  1013. return
  1014. }
  1015. // All values are unique
  1016. _, _, res = sendTestRequest(queryURL+"/"+id+"/quickfilter/1?limit=10", "GET", nil)
  1017. if res != `
  1018. {
  1019. "frequencies": [
  1020. 1,
  1021. 1,
  1022. 1,
  1023. 1,
  1024. 1,
  1025. 1,
  1026. 1,
  1027. 1,
  1028. 1,
  1029. 1
  1030. ],
  1031. "values": [
  1032. "test",
  1033. "test1",
  1034. "test10",
  1035. "test11",
  1036. "test12",
  1037. "test13",
  1038. "test14",
  1039. "test15",
  1040. "test16",
  1041. "test17"
  1042. ]
  1043. }`[1:] {
  1044. t.Error("Unexpected result: ", res)
  1045. return
  1046. }
  1047. // All values are the same
  1048. _, _, res = sendTestRequest(queryURL+"/"+id+"/quickfilter/3", "GET", nil)
  1049. if res != `
  1050. {
  1051. "frequencies": [
  1052. 19
  1053. ],
  1054. "values": [
  1055. "foo"
  1056. ]
  1057. }`[1:] {
  1058. t.Error("Unexpected result: ", res)
  1059. return
  1060. }
  1061. // Test error cases
  1062. _, _, res = sendTestRequest(queryURL+"/"+id+"/quickfilter/4", "GET", nil)
  1063. if res != "Invalid query result column" {
  1064. t.Error("Unexpected result: ", res)
  1065. return
  1066. }
  1067. _, _, res = sendTestRequest(queryURL+"/"+id+"/quickfilter/1?limit=-5", "GET", nil)
  1068. if res != "Invalid parameter value: limit should be a positive integer number" {
  1069. t.Error("Unexpected result: ", res)
  1070. return
  1071. }
  1072. _, _, res = sendTestRequest(queryURL+"/"+id+"/quickfilter/", "GET", nil)
  1073. if res != "Need a query result column to filter" {
  1074. t.Error("Unexpected result: ", res)
  1075. return
  1076. }
  1077. _, _, res = sendTestRequest(queryURL+"/"+id+"xx/quickfilter/2", "GET", nil)
  1078. if res != "Unknown query result" {
  1079. t.Error("Unexpected result: ", res)
  1080. return
  1081. }
  1082. _, _, res = sendTestRequest(queryURL, "GET", nil)
  1083. if res != "Need a result ID and an operation" {
  1084. t.Error("Unexpected result: ", res)
  1085. return
  1086. }
  1087. _, _, res = sendTestRequest(queryURL+"/"+id+"/foo/", "GET", nil)
  1088. if res != "Unknown operation: foo" {
  1089. t.Error("Unexpected result: ", res)
  1090. return
  1091. }
  1092. }