LockManagerTests.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. const { expect } = require('chai')
  2. const sinon = require('sinon')
  3. const mockFs = require('mock-fs')
  4. const OError = require('@overleaf/o-error')
  5. const LockManager = require('../../../app/js/LockManager')
  6. const Errors = require('../../../app/js/Errors')
  7. describe('LockManager', function () {
  8. beforeEach(function () {
  9. this.lockFile = '/local/compile/directory/.project-lock'
  10. mockFs({
  11. '/local/compile/directory': {},
  12. })
  13. this.clock = sinon.useFakeTimers()
  14. })
  15. afterEach(function () {
  16. mockFs.restore()
  17. this.clock.restore()
  18. })
  19. describe('when the lock is available', function () {
  20. it('the lock can be acquired', async function () {
  21. await LockManager.acquire(this.lockFile)
  22. })
  23. it('acquiring a lock in a nonexistent directory throws an error with debug info', async function () {
  24. const err = await expect(
  25. LockManager.acquire('/invalid/path/.project-lock')
  26. ).to.be.rejected
  27. const info = OError.getFullInfo(err)
  28. expect(info).to.have.keys(['statLock', 'statDir', 'readdirDir'])
  29. expect(info.statLock.code).to.equal('ENOENT')
  30. expect(info.statDir.code).to.equal('ENOENT')
  31. expect(info.readdirDir.code).to.equal('ENOENT')
  32. })
  33. })
  34. describe('after the lock is acquired', function () {
  35. beforeEach(async function () {
  36. this.lock = await LockManager.acquire(this.lockFile)
  37. })
  38. it("the lock can't be acquired again", function (done) {
  39. const promise = LockManager.acquire(this.lockFile)
  40. // runAllAsync() will advance through time until there are no pending
  41. // timers or promises. It interferes with Mocha's promise interface, so
  42. // we use Mocha's callback interface for this test.
  43. this.clock.runAllAsync()
  44. expect(promise)
  45. .to.be.rejectedWith(Errors.AlreadyCompilingError)
  46. .then(() => {
  47. done()
  48. })
  49. .catch(err => {
  50. done(err)
  51. })
  52. })
  53. it('the lock can be acquired again after an expiry period', async function () {
  54. // The expiry time is 5 minutes. Let's wait 10 minutes.
  55. this.clock.tick(10 * 60 * 1000)
  56. await LockManager.acquire(this.lockFile)
  57. })
  58. it('the lock can be acquired again after it was released', async function () {
  59. this.lock.release()
  60. await LockManager.acquire(this.lockFile)
  61. })
  62. })
  63. })