require "redis" require "lohm" require "debug" function debug.dump(tbl) local function tcopy(t) local nt={}; for i,v in pairs(t) do nt[i]=v end; return nt end local function printy(thing, prefix, tablestack) local t = type(thing) if t == "nil" then return "nil" elseif t == "string" then return string.format('%q', thing) elseif t == "number" then return tostring(thing) elseif t == "function" then local info = debug.getinfo(thing) local source = info.source if info.linedefined then source = source .. ":" .. info.linedefined .. " - " .. info.lastlinedefined end if info.name then return ("%s %s: %s"):format(info.namewhat, info.name, source) else return "function " .. source end elseif t == "table" then if tablestack and tablestack[thing] then return string.format("%s (recursion)", tostring(thing)) end local kids, pre, substack = {}, " " .. prefix, (tablestack and tcopy(tablestack) or {}) substack[thing]=true for k, v in pairs(thing) do table.insert(kids, string.format('%s%s= %s,',pre,printy(k, ''),printy(v, pre, substack))) end return string.format("%s{\n%s\n%s}", tostring(thing), table.concat(kids, "\n"), prefix) else return tostring(thing) end end local ret = printy(tbl, "", {}) return ret end function debug.print(...) local buffer = {} for i, v in pairs{...} do table.insert(buffer, debug.dump(v)) end local res = table.concat(buffer, " ") print(res) return ... end local function newr() local redis = Redis.connect() redis:select(14) redis:flushdb() return redis end if not telescope then function assert_type(var, typ) return assert(type(var)==typ, "wrong type") end function assert_true(...) for i, v in pairs{...} do assert(v and v) end end function context(lbl, tests) return tests() end function test(lbl, test) return test() end function assert_equal(a, ...) for i, b in pairs{...} do assert(a==b) end return true end function assert_false(...) for i,v in pairs{...} do assert(not v) end end function assert_nil(...) for i,v in pairs{...} do assert(type(v)=='nil') end end end context("Initialization", function() test("Can use open redis connection", function() local redis = newr() assert(redis:ping()) local res = assert(lohm.new({key="foo:%s"}, redis)) assert_type(res,'table') end) test("Model / Data prototype init", function() local M = lohm.new({ key="foobar:%s", object={ getFoo = function(self) return self.foo end }, model={ getFirst = function(self) return self:findOne(1) end } }, newr()) assert_equal(M:new({foo=11}):getFoo(), 11) --assert_true(lohm.isModel(M)) M:getFirst() end) end) context("Basic manipulation", function() test("insertion / autoincrement id counter / lookup by id / deletion", function() local redis = newr() local Model = lohm.new({key="foo:%s"}, redis) local m = Model:new{foo='barbar'} m:save() local k, id = m:getKey(), m:getId() m:set('barbar','baz'):save() assert(m:getId()==id) local checkM = assert(Model:findOne(id)) assert_true( rawget(checkM,'barbar')=="baz" ) assert_true( "barbar"==checkM.foo ) assert(checkM:delete()) local notfound = Model[tonumber(id)] assert_true(not notfound) end) end) context("Sets", function() test("Rudimentary set manipulation", function() local r = newr() local Set = lohm.set({key="setty:%s"}, r) s=Set:new():add('foo', "bar","baz") s:save() local setId = s:getId() local sprime = Set[setId] assert_true(r:sismember(sprime:getKey(), 'foo')) assert_false(r:sismember(sprime:getKey(), 'bax')) s:remove("foo", "bax") s:save() assert_equal(#s, 2) assert_equal(#Set[setId], 2) end) test("Sets as references", function() local r = newr() local Foo = lohm.new({key="foohash:%s"}, r) local Set = lohm.new({key="refset:%s", type='set', reference = Foo}, r) local s = Set:new() table.insert(s, (Foo:new({bar='baz'}))) s:save() local fooId = s[1]:getId() assert_true(Foo[fooId].bar=='baz') end) end) context("Indexing", function() test("Storage and Retrieval with index", function() local M = lohm.new({ key="testindexing:%s", index = {"i1","i2", "i3"} }, newr()) local findme=math.random(1,300) local find_id, findey for i=1, 300 do local m=assert(M:new{i1=math.random(1000), i2=math.random(1000), i3=math.random(1,2)}:save()) if i==findme then findey, find_id=m, m:getId() end end assert_equal(#assert(M:findByAttr{i3=1})+#assert(M:findByAttr{i3=2}), 300) local res = M:findByAttr(findey) assert_equal(res[1].i3, tostring(findey.i3)) assert_equal(#res, 1) assert_equal(res[1].i3, tostring(findey.i3)) for i, v in pairs(res[1]) do assert_equal(tostring(v), tostring(findey[i])) end local experiment_one = res[1] experiment_one.i3="baconated grapefruit" experiment_one:save() experiment_one.i3=nil experiment_one:save() end) end) context("References", function() test("direct reference manipulation", function() local r = newr() local Moo = lohm.hash({key="moo:%s"}, r) local Thing = lohm.hash({ key="thing:%s", attributes = { moo = Moo } }, r) local t = Thing:new{ foo="bar" } local m = Moo:new({ bar="baz" }):save() t.moo = m t:save() local t1 = Thing:findOne(t:getId()) assert_equal(t1.moo:getId(), '1') t1.moo.bar="17" t1:save() local t1prime = Thing:findOne(t1:getId()) assert_equal(t1prime.moo.bar, t1.moo.bar) t1:delete() assert_nil(Thing[tonumber(t:getId())]) local t2 = Thing:new({z="9", moo=Moo:new({aux='bax'})}):save() end) --[[ test("Deletion", function() local r = newr() local Foo = lohm.new({key="foo:%s"}, r) local Bar = lohm.new({key="bar:%s", attributes={ foo = Foo } }, r) local HardBar = lohm.new({key="hardBar:%s", attributes = { foo = Foo } }, r) local foo1 = Foo:new({attr="foo1"}):save() local foo2 = Foo:new({attr="foo2"}):save() local bar = Bar:new({foo=foo1, bar=11}):save() foo2.test="test" local hardBar = HardBar:new({foo=foo2, bar=9}):save() local ids = {} for i, v in pairs{foo1=foo1, foo2=foo2, hardBar=hardBar, bar = bar} do ids[i]=v:getId() end assert_equal(Bar:findOne(ids.bar):getId(), bar:getId()) bar:delete() assert_true(not Bar:findOne(ids.bar)) assert(Foo:findOne(ids.foo1)) assert_equal(HardBar:findOne(ids.hardBar).foo.attr, foo2.attr) hardBar:delete() assert_true(not HardBar:findOne(ids.hardBar)) assert_true(not Foo:findOne(ids.foo2)) assert(Foo:findOne(ids.foo1):getId()) end) ]] test("One-to-many references (sets)", function() local r = newr() local Bar = lohm({key="barbar:%s"}, r) local Foo = lohm({ key="foo:%s", attributes= { manyBar = lohm.new({key="bars:%s", reference = Bar, type='set'}, r), oneBar = Bar } }, r) local bars = {} for i=1, 20 do local bar = Bar:new{woo=i}:save() table.insert(bars, bar) end local foo = Foo:new{oneBar = Bar:new({yes="no"}):save()} for i,v in pairs(bars) do table.insert(foo.manyBar, v) end assert_equal(foo:save(), foo) local foo_take2 = Foo:findOne(foo:getId()) assert_equal(foo_take2:getId(), foo:getId()) for i,v in pairs(foo_take2.manyBar) do assert_equal(tostring(v.woo), tostring(bars[tonumber(v.woo)].woo)) end end) end)