UNPKG

mudb

Version:

Real-time database for multiplayer games

326 lines 17.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tape = require("tape"); const schema_1 = require("../../schema"); const index_1 = require("../index"); function createTest(t, store, rda) { return function (action, stateAfter) { t.equal(store.apply(rda, action), true, JSON.stringify(action)); t.deepEqual(store.state(rda, rda.stateSchema.alloc()), stateAfter); }; } tape('constant', (t) => { const store = new index_1.MuRDAConstant(new schema_1.MuFloat64()).createStore(0); t.false(store.apply(), 'always false'); t.end(); }); tape('register', (t) => { const Durability = new index_1.MuRDARegister(new schema_1.MuFloat64()); const durabilityStore = Durability.createStore(100); t.true(durabilityStore.apply(Durability, 99.97), 'reduce durability'); t.equal(durabilityStore.state(Durability, 100), 99.97, 'get new durability'); const User = new index_1.MuRDARegister(new schema_1.MuStruct({ id: new schema_1.MuUint32(), name: new schema_1.MuUTF8(), })); const userStore = User.createStore(User.stateSchema.alloc()); const u = { id: 12345, name: 'Mikola' }; t.true(userStore.apply(User, u), 'initiate user'); t.deepEqual(userStore.state(User, User.stateSchema.alloc()), u, 'get user info'); t.isNot(userStore.state(User, User.stateSchema.alloc()), u, 'should be a copy'); t.end(); }); tape('constrain', (t) => { const R = new index_1.MuRDARegister(new schema_1.MuFloat64(), (x) => Math.max(0, Math.min(1, +x || 0))); const store = R.createStore(0); store.apply(R, 0.1); t.equal(store.state(R, 0), 0.1); store.apply(R, -0.1); t.equal(store.state(R, 0), 0); store.apply(R, 1.1); t.equal(store.state(R, 0), 1); store.apply(R, NaN); t.equal(store.state(R, 0), 0); t.end(); }); tape('list of lists', (t) => { const L = new index_1.MuRDAList(new index_1.MuRDAList(new index_1.MuRDARegister(new schema_1.MuInt8()))); const store = L.createStore([]); const dispatchers = L.action(store); const test = createTest(t, store, L); test(dispatchers.push([]), [[]]); test(dispatchers.update(0).push(), [[]]); test(dispatchers.update(0).push(1), [[1]]); test(dispatchers.update(0).push(2, 3), [[1, 2, 3]]); test(dispatchers.update(0).pop(), [[1, 2]]); test(dispatchers.update(0).pop(2), [[]]); test(dispatchers.update(0).pop(3), [[]]); test(dispatchers.update(0).unshift(5), [[5]]); test(dispatchers.update(0).unshift(1, 3), [[1, 3, 5]]); test(dispatchers.update(0).update(2)(6), [[1, 3, 6]]); test(dispatchers.update(0).splice(0, 0, 0), [[0, 1, 3, 6]]); test(dispatchers.update(0).splice(2, 0, 2), [[0, 1, 2, 3, 6]]); test(dispatchers.update(0).splice(4, 0, 4, 5), [[0, 1, 2, 3, 4, 5, 6]]); test(dispatchers.update(0).splice(7, 1), [[0, 1, 2, 3, 4, 5, 6]]); test(dispatchers.update(0).splice(2, 2), [[0, 1, 4, 5, 6]]); test(dispatchers.update(0).splice(1, 3, 5, 4, 1), [[0, 5, 4, 1, 6]]); test(dispatchers.update(0).swap(1, 3), [[0, 1, 4, 5, 6]]); test(dispatchers.update(0).swap(4, 0), [[6, 1, 4, 5, 0]]); test(dispatchers.update(0).swap(4, 4), [[6, 1, 4, 5, 0]]); test(dispatchers.update(0).swap(4, 5), [[6, 1, 4, 5, 0]]); test(dispatchers.update(0).sort((a, b) => a - b), [[0, 1, 4, 5, 6]]); test(dispatchers.update(0).reverse(), [[6, 5, 4, 1, 0]]); test(dispatchers.update(0).reverse(), [[0, 1, 4, 5, 6]]); test(dispatchers.update(0).shift(), [[1, 4, 5, 6]]); test(dispatchers.update(0).shift(2), [[5, 6]]); test(dispatchers.update(0).shift(3), [[]]); test(dispatchers.update(0).reset([1, 2, 3]), [[1, 2, 3]]); test(dispatchers.update(0).reset([4, 5, 6]), [[4, 5, 6]]); test(dispatchers.update(0).clear(), [[]]); t.end(); }); tape('list of structs of list of structs', (t) => { const L = new index_1.MuRDAList(new index_1.MuRDAStruct({ s: new index_1.MuRDAStruct({ f: new index_1.MuRDARegister(new schema_1.MuFloat64()), }), l: new index_1.MuRDAList(new index_1.MuRDAStruct({ u: new index_1.MuRDARegister(new schema_1.MuUTF8()), })), })); const store = L.createStore([]); const dispatchers = L.action(store); const test = createTest(t, store, L); test(dispatchers.pop(), []); test(dispatchers.shift(), []); test(dispatchers.push({ s: { f: 11.11 }, l: [] }, { s: { f: 22.11 }, l: [{ u: '22.11' }] }), [{ s: { f: 11.11 }, l: [] }, { s: { f: 22.11 }, l: [{ u: '22.11' }] }]); test(dispatchers.update(0).s.f(11.22), [{ s: { f: 11.22 }, l: [] }, { s: { f: 22.11 }, l: [{ u: '22.11' }] }]); test(dispatchers.update(1).s.f(22.22), [{ s: { f: 11.22 }, l: [] }, { s: { f: 22.22 }, l: [{ u: '22.11' }] }]); test(dispatchers.update(1).l.update(0).u('22.22'), [{ s: { f: 11.22 }, l: [] }, { s: { f: 22.22 }, l: [{ u: '22.22' }] }]); test(dispatchers.pop(), [{ s: { f: 11.22 }, l: [] }]); test(dispatchers.update(0).l.pop(), [{ s: { f: 11.22 }, l: [] }]); test(dispatchers.update(0).l.shift(), [{ s: { f: 11.22 }, l: [] }]); test(dispatchers.update(0).l.push({ u: '11.11' }, { u: '11.22' }, { u: '11.33' }), [{ s: { f: 11.22 }, l: [{ u: '11.11' }, { u: '11.22' }, { u: '11.33' }] }]); test(dispatchers.update(0).l.pop(), [{ s: { f: 11.22 }, l: [{ u: '11.11' }, { u: '11.22' }] }]); test(dispatchers.update(0).l.shift(), [{ s: { f: 11.22 }, l: [{ u: '11.22' }] }]); test(dispatchers.update(0).l.unshift({ u: '11.00' }, { u: '11.11' }), [{ s: { f: 11.22 }, l: [{ u: '11.00' }, { u: '11.11' }, { u: '11.22' }] }]); test(dispatchers.update(0).l.splice(1, 0, { u: '11.33' }), [{ s: { f: 11.22 }, l: [{ u: '11.00' }, { u: '11.33' }, { u: '11.11' }, { u: '11.22' }] }]); test(dispatchers.update(0).l.splice(1, 0, { u: '11.11' }, { u: '11.22' }), [{ s: { f: 11.22 }, l: [{ u: '11.00' }, { u: '11.11' }, { u: '11.22' }, { u: '11.33' }, { u: '11.11' }, { u: '11.22' }] }]); test(dispatchers.update(0).l.splice(1, 1), [{ s: { f: 11.22 }, l: [{ u: '11.00' }, { u: '11.22' }, { u: '11.33' }, { u: '11.11' }, { u: '11.22' }] }]); test(dispatchers.update(0).l.splice(1, 2), [{ s: { f: 11.22 }, l: [{ u: '11.00' }, { u: '11.11' }, { u: '11.22' }] }]); test(dispatchers.update(0).l.clear(), [{ s: { f: 11.22 }, l: [] }]); test(dispatchers.update(0).l.reset([{ u: '11.33' }, { u: '11.44' }, { u: '11.55' }]), [{ s: { f: 11.22 }, l: [{ u: '11.33' }, { u: '11.44' }, { u: '11.55' }] }]); t.end(); }); tape('map of constants', (t) => { const M = new index_1.MuRDAMap(new schema_1.MuVarint(), new index_1.MuRDAConstant(new schema_1.MuDate())); const store = M.createStore(M.stateSchema.identity); const dispatchers = M.action(store); const test = createTest(t, store, M); test(dispatchers.clear(), {}); test(dispatchers.move(0, 1), {}); test(dispatchers.remove(0), {}); test(dispatchers.reset({}), {}); test(dispatchers.set(0, new Date(0)), { 0: new Date(0) }); test(dispatchers.set(1, new Date(1000)), { 0: new Date(0), 1: new Date(1000) }); test(dispatchers.move(1, 0), { 0: new Date(1000) }); test(dispatchers.move(0, 1), { 1: new Date(1000) }); test(dispatchers.set(2, new Date(2000)), { 1: new Date(1000), 2: new Date(2000) }); test(dispatchers.move(2, 1), { 1: new Date(2000) }); test(dispatchers.move(2, 0), { 1: new Date(2000) }); test(dispatchers.remove(1), {}); test(dispatchers.move(1, 0), {}); test(dispatchers.reset({ 0: new Date(0), 1: new Date(1000) }), { 0: new Date(0), 1: new Date(1000) }); test(dispatchers.reset({ 2: new Date(2000) }), { 2: new Date(2000) }); test(dispatchers.clear(), {}); test(dispatchers.reset({ 0: new Date(0) }), { 0: new Date(0) }); let action = dispatchers.remove(0); action.data.id = -1; t.equal(store.apply(M, action), false, JSON.stringify(action)); t.deepEqual(store.state(M, M.stateSchema.alloc()), { 0: new Date(0) }); action = dispatchers.move(0, 1); action.data.id = -1; t.equal(store.apply(M, action), false, JSON.stringify(action)); t.deepEqual(store.state(M, M.stateSchema.alloc()), { 0: new Date(0) }); action = dispatchers.set(1, new Date(1)); action.type = 'foo'; t.equal(store.apply(M, action), false, JSON.stringify(action)); t.deepEqual(store.state(M, M.stateSchema.alloc()), { 0: new Date(0) }); t.end(); }); tape('map of maps of registers', (t) => { const M = new index_1.MuRDAMap(new schema_1.MuASCII(), new index_1.MuRDAMap(new schema_1.MuASCII(), new index_1.MuRDARegister(new schema_1.MuVarint()))); const store = M.createStore(M.stateSchema.identity); const dispatchers = M.action(store); const test = createTest(t, store, M); test(dispatchers.update('a').clear(), {}); test(dispatchers.update('a').set('a', 0), {}); test(dispatchers.update('a').update('a')(1), {}); test(dispatchers.update('a').move('a', 'b'), {}); test(dispatchers.update('a').remove('b'), {}); test(dispatchers.update('a').reset({ 'a': 0 }), {}); test(dispatchers.set('foo', {}), { foo: {} }); test(dispatchers.update('foo').set('a', 0), { foo: { a: 0 } }); test(dispatchers.update('foo').set('a', 1), { foo: { a: 1 } }); test(dispatchers.update('foo').move('a', 'b'), { foo: { b: 1 } }); test(dispatchers.update('foo').move('b', 'b'), { foo: { b: 1 } }); test(dispatchers.update('foo').set('a', 0), { foo: { a: 0, b: 1 } }); test(dispatchers.update('foo').move('b', 'a'), { foo: { a: 1 } }); test(dispatchers.update('foo').move('b', 'c'), { foo: { a: 1 } }); test(dispatchers.update('foo').remove('a'), { foo: {} }); test(dispatchers.update('foo').move('a', 'b'), { foo: {} }); test(dispatchers.update('foo').reset({ a: 0, b: 1 }), { foo: { a: 0, b: 1 } }); test(dispatchers.update('foo').reset({ c: 2 }), { foo: { c: 2 } }); test(dispatchers.update('foo').update('c')(3), { foo: { c: 3 } }); test(dispatchers.update('foo').clear(), { foo: {} }); test(dispatchers.clear(), {}); test(dispatchers.reset({ foo: { bar: 0 } }), { foo: { bar: 0 } }); let action = dispatchers.update('foo').update('bar')(1); action.data.id = -1; t.equal(store.apply(M, action), false, JSON.stringify(action)); t.deepEqual(store.state(M, M.stateSchema.alloc()), { foo: { bar: 0 } }); action = dispatchers.update('foo').update('bar')(1); action.data.action.data.id = -1; t.equal(store.apply(M, action), false, JSON.stringify(action)); t.deepEqual(store.state(M, M.stateSchema.alloc()), { foo: { bar: 0 } }); t.end(); }); tape('map of structs', (t) => { const M = new index_1.MuRDAMap(new schema_1.MuVarint(), new index_1.MuRDAStruct({ b: new index_1.MuRDARegister(new schema_1.MuBoolean()), v: new index_1.MuRDARegister(new schema_1.MuVarint()), u: new index_1.MuRDARegister(new schema_1.MuUTF8()), d: new index_1.MuRDAConstant(new schema_1.MuDate()), })); const store = M.createStore(M.stateSchema.identity); const dispatchers = M.action(store); const test = createTest(t, store, M); test(dispatchers.set(127, { b: false, v: 0, u: '', d: new Date(0) }), { 127: { b: false, v: 0, u: '', d: new Date(0) } }); test(dispatchers.move(127, 128), { 128: { b: false, v: 0, u: '', d: new Date(0) } }); test(dispatchers.update(128).b(true), { 128: { b: true, v: 0, u: '', d: new Date(0) } }); test(dispatchers.update(128).v(1), { 128: { b: true, v: 1, u: '', d: new Date(0) } }); test(dispatchers.update(128).u('Iñtërnâtiônàlizætiøn☃💩'), { 128: { b: true, v: 1, u: 'Iñtërnâtiônàlizætiøn☃💩', d: new Date(0) } }); test(dispatchers.remove(128), {}); test(dispatchers.reset({ 128: { b: true, v: 1, u: 'Iñtërnâtiônàlizætiøn☃💩', d: new Date(0) } }), { 128: { b: true, v: 1, u: 'Iñtërnâtiônàlizætiøn☃💩', d: new Date(0) } }); test(dispatchers.clear(), {}); t.end(); }); tape('map of structs of structs of structs', (t) => { const M = new index_1.MuRDAMap(new schema_1.MuASCII(), new index_1.MuRDAStruct({ s: new index_1.MuRDAStruct({ s: new index_1.MuRDAStruct({ v: new index_1.MuRDARegister(new schema_1.MuVarint()), }), }), })); const store = M.createStore(M.stateSchema.identity); const dispatchers = M.action(store); const test = createTest(t, store, M); test(dispatchers.set('foo', { s: { s: { v: 0 } } }), { foo: { s: { s: { v: 0 } } } }); test(dispatchers.move('foo', 'bar'), { bar: { s: { s: { v: 0 } } } }); test(dispatchers.update('bar').s.s.v(128), { bar: { s: { s: { v: 128 } } } }); test(dispatchers.move('bar', 'baz'), { baz: { s: { s: { v: 128 } } } }); test(dispatchers.update('bar').s.s.v(129), { baz: { s: { s: { v: 128 } } } }); test(dispatchers.remove('baz'), {}); test(dispatchers.reset({ bar: { s: { s: { v: 128 } } }, baz: { s: { s: { v: 0 } } }, }), { bar: { s: { s: { v: 128 } } }, baz: { s: { s: { v: 0 } } }, }); test(dispatchers.move('bar', 'baz'), { baz: { s: { s: { v: 128 } } } }); test(dispatchers.clear(), {}); t.end(); }); tape('map of structs of maps of structs', (t) => { const M = new index_1.MuRDAMap(new schema_1.MuVarint(), new index_1.MuRDAStruct({ m: new index_1.MuRDAMap(new schema_1.MuASCII(), new index_1.MuRDAStruct({ v: new index_1.MuRDARegister(new schema_1.MuVarint()), })), })); const store = M.createStore(M.stateSchema.identity); const dispatchers = M.action(store); const test = createTest(t, store, M); test(dispatchers.set(16383, { m: {} }), { 16383: { m: {} } }); test(dispatchers.move(16383, 16384), { 16384: { m: {} } }); test(dispatchers.update(16384).m.set('foo', { v: 127 }), { 16384: { m: { foo: { v: 127 } } } }); test(dispatchers.update(16384).m.move('foo', 'bar'), { 16384: { m: { bar: { v: 127 } } } }); test(dispatchers.update(16384).m.update('bar').v(128), { 16384: { m: { bar: { v: 128 } } } }); test(dispatchers.update(16384).m.update('foo').v(128), { 16384: { m: { bar: { v: 128 } } } }); test(dispatchers.update(16384).m.remove('bar'), { 16384: { m: {} } }); test(dispatchers.update(16384).m.reset({ foo: { v: 127 }, bar: { v: 128 }, }), { 16384: { m: { foo: { v: 127 }, bar: { v: 128 }, } } }); test(dispatchers.update(16384).m.move('foo', 'bar'), { 16384: { m: { bar: { v: 127 } } } }); test(dispatchers.update(16384).m.clear(), { 16384: { m: {} } }); t.end(); }); tape('non-empty output map', (t) => { const M = new index_1.MuRDAMap(new schema_1.MuVarint(), new index_1.MuRDAConstant(new schema_1.MuDate())); const store = M.createStore(M.stateSchema.identity); const dispatchers = M.action(store); t.deepEqual(store.state(M, {}), {}); t.deepEqual(store.state(M, { 0: new Date(0) }), {}); store.apply(M, dispatchers.reset({ 127: new Date(127), 128: new Date(128) })); t.deepEqual(store.state(M, { 0: new Date(0) }), { 127: new Date(127), 128: new Date(128) }); t.deepEqual(store.state(M, { 127: new Date(0) }), { 127: new Date(127), 128: new Date(128) }); t.deepEqual(store.state(M, { 127: new Date(127), 128: new Date(128) }), { 127: new Date(127), 128: new Date(128) }); store.apply(M, dispatchers.remove(127)); t.deepEqual(store.state(M, { 127: new Date(127), 128: new Date(128) }), { 128: new Date(128) }); t.end(); }); tape('struct', (t) => { const S = new index_1.MuRDAStruct({ c: new index_1.MuRDAConstant(new schema_1.MuInt8()), rf: new index_1.MuRDARegister(new schema_1.MuFloat64()), rs: new index_1.MuRDARegister(new schema_1.MuStruct({ f: new schema_1.MuFloat64(), u: new schema_1.MuUTF8(), })), s: new index_1.MuRDAStruct({ rf: new index_1.MuRDARegister(new schema_1.MuFloat64()), rs: new index_1.MuRDARegister(new schema_1.MuStruct({ f: new schema_1.MuFloat64(), u: new schema_1.MuUTF8(), })), s: new index_1.MuRDAStruct({ rf: new index_1.MuRDARegister(new schema_1.MuFloat64()), rs: new index_1.MuRDARegister(new schema_1.MuStruct({ f: new schema_1.MuFloat64(), u: new schema_1.MuUTF8(), })), }), }), }); const store = S.createStore(S.stateSchema.identity); const dispatcher = S.action(store); const actions = []; actions.push(dispatcher.rf(11.11)); actions.push(dispatcher.rs({ f: 22.22, u: 'a' })); actions.push(dispatcher.s.rf(33.33)); actions.push(dispatcher.s.rs({ f: 44.44, u: 'b' })); actions.push(dispatcher.s.s.rf(55.55)); actions.push(dispatcher.s.s.rs({ f: 66.66, u: 'Iñtërnâtiônàlizætiøn☃💩' })); for (let i = 0; i < actions.length; ++i) { t.true(store.apply(S, actions[i]), JSON.stringify(actions[i])); } t.deepEqual(store.state(S, S.stateSchema.alloc()), { c: 0, rf: 11.11, rs: { f: 22.22, u: 'a' }, s: { rf: 33.33, rs: { f: 44.44, u: 'b' }, s: { rf: 55.55, rs: { f: 66.66, u: 'Iñtërnâtiônàlizætiøn☃💩' }, }, }, }); t.end(); }); //# sourceMappingURL=apply.js.map