local utils = require 'lime.utils' local test_utils = require 'tests.utils' local shared_state = require 'shared-state' local test_dir describe('LiMe Utils tests #sharedstate', function() it('test load a new and empty db', function() shared_state.DATA_DIR = test_dir local sharedState = shared_state.SharedState:new('foo') local data = sharedState:get() assert.are.same({}, data) end) before_each('', function() test_dir = test_utils.setup_test_dir() shared_state.DATA_DIR = test_dir end) after_each('', function() test_utils.teardown_test_dir() end) it('test insert new data to empty db', function() local sharedState = shared_state.SharedState:new('foo') sharedState:insert({ bar = 'foo', baz = 'qux' }) local db = sharedState:get() assert.is.equal('foo', db.bar.data) assert.is.equal('qux', db.baz.data) end) it('test remove data', function() local sharedState = shared_state.SharedState:new('foo') sharedState:insert({ bar = 'foo' }) sharedState:remove({'bar'}) local db = sharedState:get() assert.is_nil(db.bar.data) end) it('test two instances with different dataTypes are independent', function () local a = shared_state.SharedState:new('A') a:insert({ bar = 'foo' }) local b = shared_state.SharedState:new('B') b:insert({ baz = 'qux' }) local a_db = a:get() assert.is.equal('foo', a_db.bar.data) assert.is.equal(nil, a_db.baz) local b_db = b:get() assert.is.equal('qux', b_db.baz.data) assert.is.equal(nil, b_db.bar) end) it('test two instances with the same dataType have the same data', function () local a = shared_state.SharedState:new('foo') a:insert({ bar = 'foo' }) local b = shared_state.SharedState:new('foo') b:insert({ baz = 'qux' }) local a_db = a:get() assert.is.equal('foo', a_db.bar.data) assert.is.equal('qux', a_db.baz.data) local b_db = b:get() assert.is.equal('qux', b_db.baz.data) assert.is.equal('foo', b_db.bar.data) end) it('test data is removed if bleachTTL reaches 0', function () local sharedState = shared_state.SharedState:new('foo') sharedState:insert({ bar = 'foo' }, 1) assert.is.equal('foo', sharedState:get().bar.data) sharedState:bleach() assert.is.equal(nil, sharedState:get().bar) end) it('test merge data from remote db with bigger ttl', function() local sharedStateA = shared_state.SharedState:new('A') local sharedStateB = shared_state.SharedState:new('B') sharedStateA:insert({ bar = 'foo', baz = 'qux', zig = 'zag'}) sharedStateA:bleach() sharedStateB:insert({ zig = 'very_old_zag'}) sharedStateB:bleach() sharedStateB:bleach() sharedStateB:insert({ bar = 'new_foo', baz = 'new_qux' }) sharedStateA:merge(sharedStateB:get()) local dbA = sharedStateA:get() assert.is.equal(dbA.bar.data, 'new_foo') assert.is.equal(dbA.baz.data, 'new_qux') assert.is.equal(dbA.zig.data, 'zag') end) it('test same process locks dont lock but #locks', function() shared_state.DATA_DIR = test_dir local sharedStateA = shared_state.SharedState:new('foo') assert.is_false(sharedStateA.locked) sharedStateA:lock() assert.is_true(sharedStateA.locked) -- locks in the same process don't lock local sharedStateB = shared_state.SharedState:new('foo') sharedStateB:lock() assert.is_true(sharedStateB.locked) -- but for other process it does lock script = [[#!/usr/bin/lua shared_state = require('shared-state') shared_state.DATA_DIR = ']] .. test_dir .. [[' ss = shared_state.SharedState:new('foo') maxwait_s = 0 ss:lock(maxwait_s) ]] local f = io.open(test_dir .. "script.lua", "w") f:write(script) f:close() local exit_code = utils.unsafe_shell("lua "..test_dir .. "script.lua; echo -n $?") assert.equal(shared_state.ERROR_LOCK_FAILED, tonumber(exit_code)) end) end) describe('Shared State MultiWriter tests #sharedstatemultiwriter', function() before_each('', function() test_dir = test_utils.setup_test_dir() shared_state.PERSISTENT_DATA_DIR = test_dir end) after_each('', function() test_utils.teardown_test_dir() end) it('test insert new data', function() local ss = shared_state.SharedStateMultiWriter:new('foo') stub(shared_state, "_getFortune", function () return 100 end) ss:insert({ bar = '123'}) local db = ss:get() assert.is.equal('123', db.bar.data) assert.is.equal(0, db.bar.changes) assert.is.equal(100, db.bar.fortune) end) it('test merge data from remote db with more changes (newer)', function() local sharedStateA = shared_state.SharedStateMultiWriter:new('A') local sharedStateB = shared_state.SharedStateMultiWriter:new('B') sharedStateA:insert({ bar = 'foo', baz = 'qux', zig = 'old_zag'}) sharedStateB:insert({ zig = 'new_zag'}) sharedStateB:insert({ zig = 'newer_zag'}) sharedStateA:merge(sharedStateB:get()) local dbA = sharedStateA:get() assert.is.equal('foo', dbA.bar.data) assert.is.equal('qux', dbA.baz.data) assert.is.equal('newer_zag', dbA.zig.data) end) it('test merge data from remote db with less changes (older)', function() local sharedStateA = shared_state.SharedStateMultiWriter:new('A') local sharedStateB = shared_state.SharedStateMultiWriter:new('B') sharedStateA:insert({ bar = 'foo', baz = 'qux', zig = 'zag'}) sharedStateA:insert({ zig = 'new_zag'}) sharedStateB:insert({ zig = 'old_zag'}) sharedStateA:merge(sharedStateB:get()) local dbA = sharedStateA:get() assert.is.equal('foo', dbA.bar.data) assert.is.equal('qux', dbA.baz.data) assert.is.equal('new_zag', dbA.zig.data) end) it('test merge data from remote db with same changes but more luck', function() local sharedStateA = shared_state.SharedStateMultiWriter:new('A') local sharedStateB = shared_state.SharedStateMultiWriter:new('B') stub(shared_state, "_getFortune", function () return 100 end) sharedStateA:insert({ bar = 'foo', baz = 'qux', zig = 'old_zag'}) stub(shared_state, "_getFortune", function () return 1000 end) sharedStateB:insert({ zig = 'new_zag'}) sharedStateA:merge(sharedStateB:get()) local dbA = sharedStateA:get() assert.is.equal('foo', dbA.bar.data) assert.is.equal('qux', dbA.baz.data) assert.is.equal('new_zag', dbA.zig.data) end) it('test merge data from remote db with same changes but less luck', function() local sharedStateA = shared_state.SharedStateMultiWriter:new('A') local sharedStateB = shared_state.SharedStateMultiWriter:new('B') stub(shared_state, "_getFortune", function () return 1000 end) sharedStateA:insert({ bar = 'foo', baz = 'qux', zig = 'new_zag'}) stub(shared_state, "_getFortune", function () return 100 end) sharedStateB:insert({ zig = 'old_zag'}) sharedStateA:merge(sharedStateB:get()) local dbA = sharedStateA:get() assert.is.equal('foo', dbA.bar.data) assert.is.equal('qux', dbA.baz.data) assert.is.equal('new_zag', dbA.zig.data) end) end)