UNPKG

matchmaker-redis

Version:

A module that helps users join some kind of social event such as a multiplayer game.

706 lines (622 loc) 18.3 kB
const _ = require('lodash') const Redis = require('ioredis') const debug = require('debug')('tests') const redis = new Redis(process.env.REDIS_URL) redis.once('connect', () => { const dbIndex = process.env.TEST_DB_NO || 1 redis.select(dbIndex) .then(runTests) .catch(err => { console.error('*** problem with TEST_DB_NO (%d): %s **\n', dbIndex, err.message.substr(err.message.indexOf('ERR ')+4)) process.exit(1) }) }) const { createEvent, autojoinEvent, getEventsFor, joinEvent, cancelEvent } = require('.')(redis) const user1 = { id: '1', alias: 'user1' } const user2 = { id: '2', alias: 'user2' } const user3 = { id: '3', alias: 'user3' } const perUserTimeoutSec = 2 function delay(seconds) { debug('delaying %d seconds', seconds) return new Promise(resolve => setTimeout(resolve, seconds * 1000)) } function testAutojoinShouldFailNoEvents() { debug('Running test AutojoinShouldFailNoEvents') return redis.flushdb() .then(() => { return autojoinEvent({ userId: user1.id, userAlias: user1.alias }) }) .then(event => { if (event) { debug('got event', event) throw new Error(`did not expect an event but got one: ${JSON.stringify(event)}`) } }) } function testAutojoinFailThenCreate() { debug('Running test AutojoinFailThenCreate') return redis.flushdb() .then(() => { return autojoinEvent({ userId: user1.id, userAlias: user1.alias }) }) .then(event => { if (event) { debug('got event', event) throw new Error(`did not expect an event but got one: ${JSON.stringify(event)}`) } return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec }) }) .then(event => { if (!event) throw new Error('failed to create event') }) } function testCreateAutoexpires() { debug('Running test CreateAutoexpires') return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec }) }) .then(function (event) { if (!event) throw new Error('failed to create event') this.createdEvent = event debug('created event', this.createdEvent) return delay(event.capacity * (perUserTimeoutSec + 1)) }) .then(function () { return getEventsFor(user1.id) }) .then(function (events) { if (_.find(events.pending, {id: this.createdEvent.id})) { debug('got events', events) throw new Error('expected event to have been expired') } }) } function testCreateThenAutojoin() { debug('Running test CreateThenAutojoin') return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec }) }) .then(function (event) { this.createdEvent = event debug('created event', this.createdEvent) return autojoinEvent({ userId: user2.id, userAlias: user2.alias, capacity: 2 }) }) .then(function (event) { debug('got event', event) if (event.id !== this.createdEvent.id) { throw new Error('expected to autojoin created event') } return event }) } function testCreateThenGet() { debug('Running test CreateThenGet') return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec }) }) .then(function (event) { this.createdEvent = event debug('created event', this.createdEvent) return getEventsFor(user1.id) }) .then(function (events) { if (!_.find(events.pending, {id: this.createdEvent.id})) { debug('got events', events) throw new Error('expected to find event since user created event') } }) } function testNoSelfWhitelist() { debug('Running test NoSelfWhitelist') return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec, whitelist: [user1.id] }) }) .then(function (event) { throw new Error('should have failed since creator is on whitelist') }) .catch(err => {}) } function testNoSelfBlacklist() { debug('Running test NoSelfBlacklist') return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec, blacklist: [user1.id] }) }) .then(function (event) { throw new Error('should have failed since creator is on blacklist') }) .catch(err => {}) } function testGetWhitelisted() { debug('Running test GetWhitelisted') return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec, whitelist: [user2.id] }) }) .then(function (event) { this.createdEvent = event debug('created event', this.createdEvent) return getEventsFor(user2.id) }) .then(events => { if (!_.find(events.pending, {id: this.createdEvent.id})) { debug('got events', events) throw new Error('expected to find event since user was on whitelist') } }) } function testAutojoinShouldFailForAlreadyJoinedUser() { debug('Running test AutojoinShouldFailForAlreadyJoinedUser') return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec }) }) .then(function (event) { this.createdEvent = event debug('created event', this.createdEvent) return autojoinEvent({ userId: user2.id, userAlias: user2.alias }) }) .then(function (event) { if (event.id !== this.createdEvent.id) { debug('got event', event) throw new Error('expected to autojoin created event') } // again return autojoinEvent({ userId: user2.id, userAlias: user2.alias }) }) .then(function (event) { if (event) { debug('got event', event) throw new Error('expected to not autojoin created event since already joined') } }) } function testNoAutojoinBlacklisted() { debug('Running test NoAutojoinBlacklisted') return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec, blacklist: [user2.id] }) }) .then(function (event) { this.createdEvent = event debug('created event', this.createdEvent) return autojoinEvent({ userId: user2.id, userAlias: user2.alias }) }) .then(function (event) { if (event && event.id === this.createdEvent.id) { debug('got event', event) throw new Error('should not have got event since user was on blacklist') } }) } function testAcceptFlow() { debug('Running test AcceptFlow') return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec, whitelist: [user2.id] }) }) .then(function (event) { this.createdEvent = event debug('created event', this.createdEvent) return joinEvent(user2.id, user2.alias, event.id) }) .then(function (event) { if (event.id !== this.createdEvent.id) { debug('got event', event) throw new Error('expected to accept event whitelisting/invite') } }) } function testAcceptShouldFailNotWhitelisted() { debug('Running test AcceptShouldFailNotWhitelisted') return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec, whitelist: [user2.id] }) }) .then(function (event) { this.createdEvent = event debug('created event', this.createdEvent) return joinEvent(user3.id, user3.alias, event.id) }) .catch(err => {}) } function testCreateExpireGetShouldBeMissing() { debug('Running test CreateExpireGetShouldBeMissing') return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec }) }) .then(function (event) { this.createdEvent = event debug('created event', this.createdEvent) return delay(perUserTimeoutSec * 2 + 1) }) .then(function () { return getEventsFor(user1.id) }) .then(function (events) { if (_.find(events.pending, {id: this.createdEvent.id})) { debug('got events', events) throw new Error('expected event to have expired') } }) } function testCancelEvent() { debug('Running test CancelEvent') return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec }) }) .then(function (event) { this.createdEvent = event debug('created event', this.createdEvent) return cancelEvent(user1.id, event.id) }) .then(function () { return getEventsFor(user1.id) }) .then(function (events) { if (_.find(events.pending, {id: this.createdEvent.id})) { debug('got events', events) throw new Error('expected event to have been canceled') } }) } function testAutojoinStartsEvent() { debug('Running test AutojoinStartsEvent') return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec }) }) .then(function (event) { this.createdEvent = event debug('created event', this.createdEvent) return autojoinEvent({ userId: user2.id, userAlias: user2.alias }) }) .then(function (event) { this.joinedEvent = event if (!event.startedAt) { debug('got event', event) throw new Error('expected event to have started') } return getEventsFor(user1.id) }) .then(function (events) { if (!_.find(events.active, {id: this.createdEvent.id})) { debug('got events', events) throw new Error(`expected event ${this.createdEvent.id} to be in active list for user1`) } if (_.find(events.pending, {id: this.createdEvent.id})) { debug('got events', events) throw new Error(`expected event ${this.createdEvent.id} to not be in pending list for user1`) } return getEventsFor(user2.id) }) .then(function (events) { if (!_.find(events.active, {id: this.joinedEvent.id})) { debug('got events', events) throw new Error(`expected event ${this.joinedEvent.id} to be in active list for user2`) } if (_.find(events.pending, {id: this.joinedEvent.id})) { debug('got events', events) throw new Error(`expected event ${this.joinedEvent.id} to not be in pending list for user2`) } }) } function testAcceptStartsEvent() { debug('Running test AcceptStartsEvent') return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec, whitelist: [user2.id] }) }) .then(function (event) { this.createdEvent = event debug('created event', this.createdEvent) return joinEvent(user2.id, user2.alias, event.id) }) .then(function (event) { if (event.id !== this.createdEvent.id) { debug('got event', event) throw new Error('expected to accept event whitelisting/invite') } this.joinedEvent = event return getEventsFor(user1.id) }) .then(function (events) { if (!_.find(events.active, {id: this.createdEvent.id})) { debug('got events', events) throw new Error(`expected event ${this.createdEvent.id} to be in active list for user1`) } if (_.find(events.pending, {id: this.createdEvent.id})) { debug('got events', events) throw new Error(`expected event ${this.createdEvent.id} to not be in pending list for user1`) } return getEventsFor(user2.id) }) .then(function (events) { if (!_.find(events.active, {id: this.joinedEvent.id})) { debug('got events', events) throw new Error(`expected event ${this.joinedEvent.id} to be in active list for user2`) } if (_.find(events.pending, {id: this.joinedEvent.id})) { debug('got events', events) throw new Error(`expected event ${this.joinedEvent.id} to not be in pending list for user2`) } }) } function testAutojoinWithNonMatchingOptionsShouldNotFindEvent() { debug('Running test AutojoinWithNonMatchingOptionsShouldNotFindEvent') const user1Options = 'opt1=foo opt2=bar opt3=42' const user2Options = 'opt1=foo opt2=baz opt3=42' return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec, params: user1Options }) }) .then(function (event) { this.createdEvent = event debug('created event', this.createdEvent) return autojoinEvent({ userId: user2.id, userAlias: user2.alias, params: user2Options }) }) .then(function (event) { if (event) { debug('got event', event) throw new Error('expected to not find autojoinable event') } }) } function testAutojoinWithMatchingOptionsShouldFindEvent() { debug('Running test AutojoinWithMatchingOptionsShouldFindEvent') const user1Options = 'opt1=quux opt2=doo opt3=84' const user2Options = user1Options return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: 2, perUserTimeoutSec, params: user1Options }) }) .then(function (event) { this.createdEvent = event debug('created event', this.createdEvent) return autojoinEvent({ userId: user2.id, userAlias: user2.alias, params: user2Options }) }) .then(function (event) { if (!event || event.id !== this.createdEvent.id) { debug('got event', event) throw new Error('expected to find created event for autojoining') } }) } function testCreateLargeEventAndCancelShouldDelist() { debug('Running test CreateLargeEventAndCancelShouldDelist') // create event that starts when 8 players join // have 2 others join then cancel it const largeEventUserCount = 8 const largeEventOptions = 'opt1=foo' return redis.flushdb() .then(() => { return createEvent({ userId: user1.id, userAlias: user1.alias, capacity: largeEventUserCount, perUserTimeoutSec, params: largeEventOptions }) }) .then(function (event) { this.createdEvent = event debug('created event', this.createdEvent) return autojoinEvent({ userId: user2.id, userAlias: user2.alias, capacity: largeEventUserCount, params: largeEventOptions }) }) .then(function (event) { if (!event || event.id !== this.createdEvent.id) { debug('got event', event) throw new Error('expected to find created event for autojoining') } return autojoinEvent({ userId: user3.id, userAlias: user3.alias, capacity: largeEventUserCount, params: largeEventOptions }) }) .then(function (event) { if (!event || event.id !== this.createdEvent.id) { debug('got event', event) throw new Error('expected to find created event for autojoining') } return cancelEvent(user1.id, this.createdEvent.id) }) .then(function () { return getEventsFor(user1.id) }) .then(function (events) { if (_.find(events.pending, {id: this.createdEvent.id})) { debug('got events', events) throw new Error('expected event to have been canceled') } return getEventsFor(user2.id) }) .then(function (events) { if (_.find(events.pending, {id: this.createdEvent.id})) { debug('got events', events) throw new Error('expected event to have been canceled') } return getEventsFor(user3.id) }) .then(function (events) { if (_.find(events.pending, {id: this.createdEvent.id})) { debug('got events', events) throw new Error('expected event to have been canceled') } }) } function runTests() { return testAutojoinShouldFailNoEvents() .then(testAutojoinFailThenCreate) .then(testCreateAutoexpires) .then(testCreateThenAutojoin) .then(testCreateThenGet) .then(testNoSelfWhitelist) .then(testNoSelfBlacklist) .then(testGetWhitelisted) .then(testAutojoinShouldFailForAlreadyJoinedUser) .then(testNoAutojoinBlacklisted) .then(testAcceptFlow) .then(testAcceptShouldFailNotWhitelisted) .then(testCreateExpireGetShouldBeMissing) .then(testCancelEvent) .then(testAutojoinStartsEvent) .then(testAcceptStartsEvent) .then(testAutojoinWithNonMatchingOptionsShouldNotFindEvent) .then(testAutojoinWithMatchingOptionsShouldFindEvent) .then(testCreateLargeEventAndCancelShouldDelist) .then(() => { console.log('all tests have passed ☑️') debug('ok') process.exit() }) .catch(err => { console.trace(err) process.exit() }) }