overleaf/services/document-updater/test/unit/js/LockManager/tryLockTests.js
Eric Mc Sween 4d70bd664f Reintroduce Node 12 and metrics upgrades
These changes were previously merged, not deployed, and reverted. This
reverts the revert.

This reverts commit a6b8c6c658b33b6eee78b8b99e43308f32211ae2, reversing
changes made to 93c98921372eed4244d22fce800716cb27eca299.
2021-04-01 15:51:00 -04:00

148 lines
4.7 KiB
JavaScript

/* eslint-disable
camelcase,
no-return-assign,
no-unused-vars,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* DS206: Consider reworking classes to avoid initClass
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
const sinon = require('sinon')
const modulePath = '../../../../app/js/LockManager.js'
const SandboxedModule = require('sandboxed-module')
describe('LockManager - trying the lock', function () {
beforeEach(function () {
let Profiler
this.LockManager = SandboxedModule.require(modulePath, {
requires: {
'@overleaf/redis-wrapper': {
createClient: () => {
return {
auth() {},
set: (this.set = sinon.stub())
}
}
},
'./Metrics': { inc() {} },
'settings-sharelatex': {
redis: {
lock: {
key_schema: {
blockingKey({ doc_id }) {
return `Blocking:${doc_id}`
}
}
}
}
},
'./Profiler': (this.Profiler = Profiler = (function () {
Profiler = class Profiler {
static initClass() {
this.prototype.log = sinon.stub().returns({ end: sinon.stub() })
this.prototype.end = sinon.stub()
}
}
Profiler.initClass()
return Profiler
})())
}
})
this.callback = sinon.stub()
return (this.doc_id = 'doc-id-123')
})
describe('when the lock is not set', function () {
beforeEach(function () {
this.lockValue = 'mock-lock-value'
this.LockManager.randomLock = sinon.stub().returns(this.lockValue)
this.set.callsArgWith(5, null, 'OK')
return this.LockManager.tryLock(this.doc_id, this.callback)
})
it('should set the lock key with an expiry if it is not set', function () {
return this.set
.calledWith(`Blocking:${this.doc_id}`, this.lockValue, 'EX', 30, 'NX')
.should.equal(true)
})
return it('should return the callback with true and the lock value', function () {
return this.callback
.calledWith(null, true, this.lockValue)
.should.equal(true)
})
})
describe('when the lock is already set', function () {
beforeEach(function () {
this.set.callsArgWith(5, null, null)
return this.LockManager.tryLock(this.doc_id, this.callback)
})
return it('should return the callback with false', function () {
return this.callback.calledWith(null, false).should.equal(true)
})
})
return describe('when it takes a long time for redis to set the lock', function () {
beforeEach(function () {
this.Profiler.prototype.end = () => 7000 // take a long time
this.Profiler.prototype.log = sinon
.stub()
.returns({ end: this.Profiler.prototype.end })
this.lockValue = 'mock-lock-value'
this.LockManager.randomLock = sinon.stub().returns(this.lockValue)
this.LockManager.releaseLock = sinon.stub().callsArgWith(2, null)
return this.set.callsArgWith(5, null, 'OK')
})
describe('in all cases', function () {
beforeEach(function () {
return this.LockManager.tryLock(this.doc_id, this.callback)
})
it('should set the lock key with an expiry if it is not set', function () {
return this.set
.calledWith(`Blocking:${this.doc_id}`, this.lockValue, 'EX', 30, 'NX')
.should.equal(true)
})
return it('should try to release the lock', function () {
return this.LockManager.releaseLock
.calledWith(this.doc_id, this.lockValue)
.should.equal(true)
})
})
describe('if the lock is released successfully', function () {
beforeEach(function () {
this.LockManager.releaseLock = sinon.stub().callsArgWith(2, null)
return this.LockManager.tryLock(this.doc_id, this.callback)
})
return it('should return the callback with false', function () {
return this.callback.calledWith(null, false).should.equal(true)
})
})
return describe('if the lock has already timed out', function () {
beforeEach(function () {
this.LockManager.releaseLock = sinon
.stub()
.callsArgWith(2, new Error('tried to release timed out lock'))
return this.LockManager.tryLock(this.doc_id, this.callback)
})
return it('should return the callback with an error', function () {
return this.callback
.calledWith(sinon.match.instanceOf(Error))
.should.equal(true)
})
})
})
})