all repos — litestore @ ff3968738e0050036548de53a8654cda0ea0d9b4

A minimalist nosql document store.

Added unit tests for HTTP API.
h3rald h3rald@h3rald.com
Sun, 28 Jan 2018 16:13:37 +0100
commit

ff3968738e0050036548de53a8654cda0ea0d9b4

parent

576ed27e967ae297627c9ba52d3e95c429893ea4

M .gitignore.gitignore

@@ -2,6 +2,7 @@ *.log.txt

nimcache *.db *.db-journal +http_api litestore*.zip litestore nakefile
A test/data/1.json

@@ -0,0 +1,57 @@

+{ + "_id": "5a6c566020d0d4ba242d6501", + "index": 0, + "guid": "55fc5e44-76d0-4336-8a06-7a47dcbf3cac", + "isActive": false, + "balance": "$1,302.38", + "picture": "http://placehold.it/32x32", + "age": 34, + "eyeColor": "brown", + "name": { + "first": "Hart", + "last": "Walters" + }, + "company": "RODEOMAD", + "email": "hart.walters@rodeomad.com", + "phone": "+1 (825) 571-3043", + "address": "389 Albemarle Terrace, Idamay, Utah, 220", + "about": "Voluptate laborum ex mollit aliquip in. Cillum reprehenderit excepteur in voluptate. Amet culpa adipisicing laborum consequat officia consectetur qui fugiat qui minim velit enim.", + "registered": "Friday, October 20, 2017 6:29 PM", + "latitude": "48.993203", + "longitude": "-129.102171", + "tags": [ + "incididunt", + "reprehenderit", + "qui", + "adipisicing", + "irure" + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "friends": [ + { + "id": 0, + "name": "Blackwell Kramer" + }, + { + "id": 1, + "name": "Petra Carson" + }, + { + "id": 2, + "name": "Vaughan Garrison" + } + ], + "greeting": "Hello, Hart! You have 6 unread messages.", + "favoriteFruit": "banana" +}
A test/data/2.json

@@ -0,0 +1,57 @@

+{ + "_id": "5a6c56606df2a810d3eb1669", + "index": 1, + "guid": "cac6e4d0-8b0c-4282-aa94-6e0dd37cc8c6", + "isActive": false, + "balance": "$2,271.65", + "picture": "http://placehold.it/32x32", + "age": 31, + "eyeColor": "green", + "name": { + "first": "Hatfield", + "last": "Randolph" + }, + "company": "CALLFLEX", + "email": "hatfield.randolph@callflex.org", + "phone": "+1 (969) 468-3496", + "address": "768 Thatford Avenue, Allensworth, Georgia, 6175", + "about": "Cupidatat reprehenderit ad est laborum Lorem eu consectetur ut mollit. Elit commodo cillum ipsum anim Lorem nostrud cillum occaecat proident. Aute aliquip officia anim aliquip. Magna culpa enim labore tempor laboris aute amet ad laborum. Fugiat Lorem velit cillum cupidatat dolore est.", + "registered": "Wednesday, September 23, 2015 6:15 PM", + "latitude": "21.356912", + "longitude": "-9.471178", + "tags": [ + "non", + "nostrud", + "consequat", + "deserunt", + "cillum" + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "friends": [ + { + "id": 0, + "name": "Rhonda Austin" + }, + { + "id": 1, + "name": "Katy Golden" + }, + { + "id": 2, + "name": "Elisabeth Willis" + } + ], + "greeting": "Hello, Hatfield! You have 10 unread messages.", + "favoriteFruit": "apple" +}
A test/data/3.json

@@ -0,0 +1,57 @@

+{ + "_id": "5a6c5660d613e4c504bbf860", + "index": 2, + "guid": "b6d68ada-df9f-4f85-a135-49a99749c0fd", + "isActive": true, + "balance": "$3,663.84", + "picture": "http://placehold.it/32x32", + "age": 31, + "eyeColor": "blue", + "name": { + "first": "Jensen", + "last": "Ayers" + }, + "company": "VERTIDE", + "email": "jensen.ayers@vertide.me", + "phone": "+1 (939) 447-2936", + "address": "131 Dank Court, Jeff, Wisconsin, 1073", + "about": "Ipsum ex occaecat culpa tempor. Amet non culpa consectetur labore eu culpa irure nostrud Lorem. Laborum in qui qui ullamco consequat reprehenderit. Ea veniam Lorem ad sunt culpa minim pariatur. Dolore anim incididunt amet ea magna sit qui pariatur adipisicing ullamco occaecat minim. Adipisicing anim Lorem consequat incididunt ad amet. Qui veniam ipsum aliqua culpa.", + "registered": "Tuesday, September 8, 2015 10:35 AM", + "latitude": "25.009142", + "longitude": "-69.645903", + "tags": [ + "fugiat", + "sunt", + "duis", + "ullamco", + "consectetur" + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "friends": [ + { + "id": 0, + "name": "Reed Hoffman" + }, + { + "id": 1, + "name": "Gail Clayton" + }, + { + "id": 2, + "name": "Snider Walsh" + } + ], + "greeting": "Hello, Jensen! You have 5 unread messages.", + "favoriteFruit": "banana" +}
A test/data/4.json

@@ -0,0 +1,57 @@

+{ + "_id": "5a6c5660692b3518d7a57db1", + "index": 3, + "guid": "bbe62851-96fd-459a-8ac6-340c7445cd4b", + "isActive": false, + "balance": "$3,489.70", + "picture": "http://placehold.it/32x32", + "age": 36, + "eyeColor": "brown", + "name": { + "first": "Lawson", + "last": "Logan" + }, + "company": "TRASOLA", + "email": "lawson.logan@trasola.co.uk", + "phone": "+1 (936) 528-3401", + "address": "731 Vine Street, Beechmont, Colorado, 7201", + "about": "Ut Lorem magna esse aute. Commodo dolor laborum consequat officia tempor anim velit labore consequat aute esse amet laboris dolore. Et voluptate Lorem fugiat magna do sunt enim culpa sunt dolor. Commodo duis nostrud veniam sunt et irure anim.", + "registered": "Tuesday, August 8, 2017 4:50 AM", + "latitude": "-84.277821", + "longitude": "-166.812995", + "tags": [ + "culpa", + "quis", + "fugiat", + "ipsum", + "labore" + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "friends": [ + { + "id": 0, + "name": "Blake Graham" + }, + { + "id": 1, + "name": "Stephens Conley" + }, + { + "id": 2, + "name": "Nadine Munoz" + } + ], + "greeting": "Hello, Lawson! You have 9 unread messages.", + "favoriteFruit": "banana" +}
A test/data/5.json

@@ -0,0 +1,57 @@

+{ + "_id": "5a6c5660d67cd83953572b88", + "index": 4, + "guid": "a3212724-6b16-405f-b826-a395e2b92e2d", + "isActive": true, + "balance": "$3,546.05", + "picture": "http://placehold.it/32x32", + "age": 21, + "eyeColor": "brown", + "name": { + "first": "Lee", + "last": "Morgan" + }, + "company": "UNDERTAP", + "email": "lee.morgan@undertap.biz", + "phone": "+1 (807) 472-3642", + "address": "192 Bokee Court, Benson, Guam, 7454", + "about": "Qui proident nisi cillum excepteur id Lorem dolor occaecat. Occaecat nulla consectetur do officia magna dolore mollit officia et aute ipsum. Magna exercitation sint eu consequat non esse cillum officia et voluptate. Est sunt reprehenderit id officia elit ut ullamco ullamco do amet veniam deserunt. Sit quis dolore laboris non eu ad labore minim incididunt sit officia. Ut ipsum dolor sunt cupidatat incididunt nulla pariatur eu nisi et irure dolor laborum.", + "registered": "Friday, August 14, 2015 7:59 PM", + "latitude": "-48.116808", + "longitude": "142.448418", + "tags": [ + "occaecat", + "ea", + "cillum", + "non", + "enim" + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "friends": [ + { + "id": 0, + "name": "Shaffer Lamb" + }, + { + "id": 1, + "name": "Dawn Hester" + }, + { + "id": 2, + "name": "Leanne Lucas" + } + ], + "greeting": "Hello, Lee! You have 5 unread messages.", + "favoriteFruit": "apple" +}
A test/data/6.json

@@ -0,0 +1,57 @@

+{ + "_id": "5a6c5660bcef6021f071db12", + "index": 5, + "guid": "0260bbfc-a408-428b-9abd-d4854ae5210a", + "isActive": true, + "balance": "$2,726.88", + "picture": "http://placehold.it/32x32", + "age": 31, + "eyeColor": "blue", + "name": { + "first": "Park", + "last": "Dillon" + }, + "company": "QUIZKA", + "email": "park.dillon@quizka.tv", + "phone": "+1 (921) 578-3355", + "address": "228 Seagate Terrace, Cumminsville, Alaska, 3910", + "about": "Nisi enim labore mollit labore consectetur aliqua mollit cupidatat laborum tempor pariatur. Incididunt reprehenderit duis veniam nostrud ut esse laboris tempor adipisicing. Aliquip amet nostrud consequat quis pariatur tempor duis cupidatat cillum elit et consectetur occaecat nisi. Et enim ea laborum esse mollit magna culpa eiusmod excepteur. Esse et tempor sint aliquip. Et dolor cupidatat eiusmod consectetur ipsum amet sunt quis. Eiusmod aute labore eu eu ipsum magna velit pariatur duis cupidatat.", + "registered": "Wednesday, October 4, 2017 9:41 PM", + "latitude": "59.653229", + "longitude": "11.735447", + "tags": [ + "ea", + "adipisicing", + "pariatur", + "voluptate", + "et" + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "friends": [ + { + "id": 0, + "name": "Joyner Ellis" + }, + { + "id": 1, + "name": "Bette Black" + }, + { + "id": 2, + "name": "Parker Holloway" + } + ], + "greeting": "Hello, Park! You have 10 unread messages.", + "favoriteFruit": "strawberry" +}
A test/data/7.json

@@ -0,0 +1,57 @@

+{ + "_id": "5a6c5660a85f5de026893e81", + "index": 6, + "guid": "afad15a9-ccea-413b-ab03-2e3dca7217bc", + "isActive": false, + "balance": "$1,611.84", + "picture": "http://placehold.it/32x32", + "age": 36, + "eyeColor": "green", + "name": { + "first": "Burgess", + "last": "Greene" + }, + "company": "XYQAG", + "email": "burgess.greene@xyqag.name", + "phone": "+1 (895) 547-2197", + "address": "881 Fanchon Place, Floriston, Kentucky, 1428", + "about": "Consequat proident excepteur eu in quis velit sint ad qui mollit aliqua. Qui aliqua cillum eiusmod incididunt esse. Consequat labore consectetur eu est id reprehenderit aute proident reprehenderit enim velit eu aliquip mollit. Nulla ut elit labore amet nostrud eu fugiat fugiat laborum. Est id nulla dolor dolor officia deserunt elit ullamco quis. In Lorem ad adipisicing aliqua.", + "registered": "Friday, August 12, 2016 8:57 AM", + "latitude": "-40.438188", + "longitude": "-80.46053", + "tags": [ + "esse", + "dolore", + "anim", + "irure", + "ad" + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "friends": [ + { + "id": 0, + "name": "Jordan Ruiz" + }, + { + "id": 1, + "name": "Leah Estes" + }, + { + "id": 2, + "name": "Elise Huffman" + } + ], + "greeting": "Hello, Burgess! You have 10 unread messages.", + "favoriteFruit": "banana" +}
A test/data/8.json

@@ -0,0 +1,57 @@

+{ + "_id": "5a6c5660d8994ed5a0b10b5a", + "index": 7, + "guid": "c3aff117-91f2-4947-a96d-77ff72e17157", + "isActive": true, + "balance": "$1,748.49", + "picture": "http://placehold.it/32x32", + "age": 24, + "eyeColor": "brown", + "name": { + "first": "Gina", + "last": "Brooks" + }, + "company": "COLUMELLA", + "email": "gina.brooks@columella.info", + "phone": "+1 (900) 466-2349", + "address": "221 Glen Street, Morriston, Virginia, 3010", + "about": "Ut proident consequat consectetur amet aute incididunt sunt. Deserunt commodo magna nostrud fugiat pariatur. Eiusmod anim tempor incididunt duis irure qui aliquip ex est aliqua laboris sunt cillum irure. Et veniam sint incididunt eiusmod fugiat enim cillum veniam amet. Veniam veniam elit quis aute adipisicing laboris enim nostrud laborum do velit.", + "registered": "Saturday, July 30, 2016 12:01 PM", + "latitude": "-11.007002", + "longitude": "-125.821486", + "tags": [ + "sit", + "minim", + "qui", + "excepteur", + "qui" + ], + "range": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "friends": [ + { + "id": 0, + "name": "Jamie Bradley" + }, + { + "id": 1, + "name": "Hunter Olson" + }, + { + "id": 2, + "name": "Gibson Mclaughlin" + } + ], + "greeting": "Hello, Gina! You have 7 unread messages.", + "favoriteFruit": "banana" +}
A test/http_api.nim

@@ -0,0 +1,124 @@

+import unittest, json, httpclient, strutils, os + +suite "LiteStore HTTP API": + + var contents = newSeq[JsonNode](0) + for i in 1..8: + contents.add parseFile("data/$1.json" % i.intToStr) + + const srv = "http://localhost:9500/" + let cli = newHttpClient() + cli.headers = newHttpHeaders({ "Content-Type": "application/json" }) + + proc jget(url: string): Response = + return cli.request(srv & url, HttpGet) + + proc jhead(url: string): Response = + return cli.request(srv & url, HttpHead) + + proc jpost(url: string, body: JsonNode): Response {.discardable.} = + return cli.request(srv & url, HttpPost, $body) + + proc jput(url: string, body: JsonNode): Response {.discardable.} = + return cli.request(srv & url, HttpPut, $body) + + proc jpatch(url: string, body: JsonNode): Response = + return cli.request(srv & url, HttpPatch, $body) + + proc jdelete(url: string): Response {.discardable.} = + return cli.request(srv & url, HttpDelete) + + proc info(prop: string): JsonNode = + return jget("info").body.parseJson[prop] + + test "GET info": + check(info("datastore_version") == %1) + + test "POST/GET/DELETE document": + var rpost = jpost("docs", contents[0]) + var id = rpost.body.parseJson["id"].getStr + check(rpost.body.parseJson["data"]["_id"] == %"5a6c566020d0d4ba242d6501") + var rget = jget("docs/$1" % id) + check(rget.body.parseJson["_id"] == %"5a6c566020d0d4ba242d6501") + var rdel = jdelete("docs/$1" % id) + check(rdel.status == "204 No Content") + check(info("total_documents") == %0) + rpost = jpost("docs/f1/f2/", contents[0]) + id = rpost.body.parseJson["id"].getStr + check(id.startsWith("f1/f2/")) + check(rpost.body.parseJson["data"]["_id"] == %"5a6c566020d0d4ba242d6501") + rget = jget("docs/$1" % id) + check(rget.body.parseJson["_id"] == %"5a6c566020d0d4ba242d6501") + rdel = jdelete("docs/$1" % id) + check(rdel.status == "204 No Content") + check(info("total_documents") == %0) + + test "PUT/PATCH/GET/DELETE document": + var rput = jput("docs/1", contents[0]) + var id = rput.body.parseJson["id"].getStr + check(id == "1") + var rget = jget("docs/1") + check(rget.body.parseJson["_id"] == %"5a6c566020d0d4ba242d6501") + rget = jget("docs?tags=t1") + check(rget.status == "404 Not Found") + var ops = """ + [ + {"op": "add", "path": "/tags/3", "value": "t1"}, + {"op": "add", "path": "/tags/4", "value": "t2"}, + {"op": "add", "path": "/tags/5", "value": "t3"} + ] + """ + var rpatch = jpatch("docs/1", ops.parseJson) + check(rpatch.status == "200 OK") + rget = jget("docs/?tags=t1") + check(rget.body.parseJson["total"] == %1) + rput = jput("docs/2", contents[1]) + ops = """ + [ + {"op": "add", "path": "/tags/3", "value": "t1"}, + {"op": "add", "path": "/tags/4", "value": "t3"} + ] + """ + rpatch = jpatch("docs/2", ops.parseJson) + check(rpatch.status == "200 OK") + rput = jput("docs/test/3", contents[2]) + rget = jget("docs/test/3") + check(rget.body.parseJson["_id"] == %"5a6c5660d613e4c504bbf860") + ops = """ + [ + {"op": "add", "path": "/tags/3", "value": "t2"}, + {"op": "add", "path": "/tags/4", "value": "t3"} + ] + """ + rpatch = jpatch("docs/test/3", ops.parseJson) + check(rpatch.status == "200 OK") + ops = """ + [ + {"op": "replace", "path": "/tags/3", "value": "t4"}, + {"op": "remove", "path": "/tags/4"} + ] + """ + rpatch = jpatch("docs/1", ops.parseJson) + check(rpatch.status == "200 OK") + rget = jget("docs/?tags=t2,t3") + check(rget.body.parseJson["total"] == %1) + jdelete("docs/1") + jdelete("docs/2") + jdelete("docs/test/3") + check(info("total_documents") == %0) + + test "HEAD/GET documents": + var ids = newSeq[string](0) + var rpost: Response; + for c in contents: + rpost = jpost("docs/test/", c) + ids.add(rpost.body.parseJson["id"].getStr) + var rhead = jhead("docs/invalid/") + check(rhead.status == "404 Not Found") + rhead = jhead("docs/test/") + check(rhead.status == "200 OK") + var rget = jget("docs/?search=Lorem&contents=false") + check(rget.body.parseJson["total"] == %5) + for i in ids: + jdelete("docs/$1" % i) + check(info("total_documents") == %0)