UNPKG

fox-wamp

Version:

Web Application Message Router/Server WAMP/MQTT

293 lines (246 loc) 8.83 kB
'use strict' // validate that memory storage has the same results as sqlite const chai = require('chai') const spies = require('chai-spies') const expect = chai.expect const assert = chai.assert const promised = require('chai-as-promised') const sqlite3 = require('sqlite3') const sqlite = require('sqlite') const WAMP = require('../lib/wamp/protocol') const { WampGate } = require('../lib/wamp/gate') const Router = require('../lib/router') const { SqliteModKv, SqliteKv } = require('../lib/sqlite/sqlitekv') const { MemEngine } = require('../lib/mono/memengine') const { DbEngine, DbBinder } = require('../lib/sqlite/dbbinder') const { MemKeyValueStorage } = require('../lib/mono/memkv') const { BaseRealm } = require('../lib/realm') const WampApi = require('../lib/wamp/api') const { getBodyValue } = require('../lib/base_gate') chai.use(promised) chai.use(spies) const TEST_REALM_NAME = 'test-realm' const makeMemRealm = async (router) => { let realm = new BaseRealm(router, new MemEngine()) realm.registerKeyValueEngine(['#'], new MemKeyValueStorage()) return realm } const makeDbRealm = async (router) => { let db = await sqlite.open({ filename: ':memory:', driver: sqlite3.Database }) let binder = new DbBinder(db) await binder.init() let realm = new BaseRealm(router, new DbEngine(binder)) let modKv = new SqliteModKv(db) await modKv.createTables() let kv = new SqliteKv(modKv, binder.getMakeId(), TEST_REALM_NAME) realm.registerKeyValueEngine(['#'], kv) return realm } const runs = [ {it: 'mem', mkRealm: makeMemRealm }, {it: 'db', mkRealm: makeDbRealm }, ] describe('55 hyper events', () => { runs.forEach((run) => { describe('storage:' + run.it, function () { let router, realm, api, mockSocket, wampGate, cli, ctx beforeEach(async () => { router = new Router() realm = await run.mkRealm(router) router.addRealm(TEST_REALM_NAME, realm) api = realm.api() mockSocket = {} wampGate = new WampGate(router) cli = router.createSession() ctx = wampGate.createContext(cli, mockSocket) realm.joinSession(cli) }) afterEach(async () => { assert.isFalse(cli.hasSendError(), cli.firstSendErrorMessage()) assert.isFalse(api.session().hasSendError(), api.session().firstSendErrorMessage()) cli.cleanup() ctx = null }) it('storage-retain-get:' + run.it, async () => { const subSpy = chai.spy(() => {}) await api.subscribe('topic1', subSpy) await api.publish('topic1', { data: 'retain-the-value' }, { retain: true, exclude_me:false }) await api.publish('topic1', { data: 'the-value-does-not-retain' }, { exclude_me:false }) let done let resultPromise = new Promise((resolve) => done = resolve) let counter = 2 let rslt = [] mockSocket.wampPkgWrite = chai.spy((msg) => { rslt.push(msg) --counter if (counter <= 0) { done() done = undefined } }) wampGate.handle(ctx, cli, [WAMP.SUBSCRIBE, 1234, { retained: true }, 'topic1']) await resultPromise expect(rslt[0][0]).to.equal(WAMP.SUBSCRIBED) expect(rslt[0][1]).to.equal(1234) expect(rslt[1][0]).to.equal(WAMP.EVENT) expect(rslt[1][3].topic).to.equal('topic1') expect(rslt[1][3].retained).to.equal(true) expect(rslt[1][4]).to.deep.equal([{ data: 'retain-the-value' }]) expect(subSpy).to.have.been.called.twice() }) it('storage-retain-weak:' + run.it, async () => { await api.publish('topic2', ['arg1', 'arg2'], { retain: true, will: null, acknowledge: true }) let storedValue = [] await realm.getKey(['topic2'], (uri, value)=>storedValue.push([uri,value])) expect(storedValue).to.deep.equal([[['topic2'], {kv:['arg1', 'arg2']}]]) await api.session().cleanup() let spyValueNotExists = chai.spy(()=>{}) await realm.getKey(['topic2'], spyValueNotExists) expect(spyValueNotExists).to.not.have.been.called() }) it('wamp-key-remove:' + run.it, async () => { await api.publish(['topic2'], { some: 'value' }, { retain: true, acknowledge: true }) let storedValue = [] await realm.getKey(['topic2'], (uri, value)=>storedValue.push([uri,value])) expect(storedValue).to.deep.equal([[['topic2'], {kv:{some:'value'}}]]) // no kwargs is sent if kwargs passed as null await api.publish('topic2', null, { retain: true, acknowledge: true }) var spyNotExists = chai.spy(()=>{}) await realm.getKey(['topic2'], spyNotExists) expect(spyNotExists).to.not.have.been.called() }) // realm must PUSH data if client has disconnect WILL registered it('push-will:' + run.it, async () => { let events = [] await api.subscribe('will.test', event => events.push(event)) const wampApi = new WampApi(realm, router.makeSessionId()) realm.joinSession(wampApi) await wampApi.publish( 'will.test', [{ info: 'event-value' }], {}, { acknowledge: true, trace: true, retain: true, will: { info: 'will-value' } } ) await wampApi.cleanup() expect(events.shift()).to.deep.equal({ info: 'event-value' }) expect(events.shift()).to.deep.equal({ args: { info: 'will-value' }}) assert.equal(0, events.length) assert.isFalse(wampApi.hasSendError(), wampApi.firstSendErrorMessage()) }) it('push-watch-for-push:' + run.it, async () => { let events = [] await api.subscribe('watch.test', event => events.push(event)) await api.publish( 'watch.test', { event: 'first event value' }, { trace: true, retain: true, exclude_me: false, acknowledge: true } ) expect(events.shift()).to.deep.equal({ event: 'first event value' }) const promiseWaitForEmpty = api.publish( 'watch.test', { event: 'second value is set when value empty' }, { trace: true, retain: true, when: null, watch: true, exclude_me: false, acknowledge: true } ) await api.publish( 'watch.test', null, { trace: true, retain: true, exclude_me: false, acknowledge: true } ) expect(events.shift()).to.deep.equal({ event: 'second value is set when value empty' }) await promiseWaitForEmpty expect(events.shift()).to.deep.equal(null) let storage = [] await realm.getKey(['watch', 'test'], (uri, value) => { storage.push([uri,getBodyValue(value)]) }) // TODO: fix-me in db // expect(storage).to.deep.equal([[['watch', 'test'], { event: 'second value is set when value empty' }]]) }) it('push-watch-for-will', async () => { let defer = [] let events = [] await api.subscribe('watch.test', event => events.push(event)) wampGate.handle(ctx, cli, [ WAMP.PUBLISH, 123456789, { retain: true, trace: true, when: null, will: null }, 'watch.test', [{ event: 'value-1' }], {} ]) // TODO: fix-me db // defer.push(assert.isRejected( api.publish( 'watch.test', { event: 'value-no-watch' }, { retain: true, trace: true, when: null, will: null, acknowledge: true } ) // )) defer.push(assert.isFulfilled( api.publish( 'watch.test', { event: 'value-2' }, { retain: true, trace: true, when: null, will: null, watch: true, acknowledge: true, exclude_me: false } ) )) await cli.cleanup() await Promise.all(defer) expect(events.shift()).to.deep.equal({ event: 'value-1' }) expect(events.shift()).to.deep.equal({ event: 'value-2' }) // ?? move below ?/ expect(events.shift()).to.not.exist expect(events.length).to.equal(0) }) }) }) })