ProjectStructureMongoLockTest.coffee 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. APP_PATH = "../../../app/js"
  2. LockManager = require "#{APP_PATH}/infrastructure/LockManager"
  3. ProjectCreationHandler = require "#{APP_PATH}/Features/Project/ProjectCreationHandler.js"
  4. ProjectGetter = require "#{APP_PATH}/Features/Project/ProjectGetter.js"
  5. ProjectEntityMongoUpdateHandler = require "#{APP_PATH}/Features/Project/ProjectEntityMongoUpdateHandler.js"
  6. UserCreator = require "#{APP_PATH}/Features/User/UserCreator.js"
  7. expect = require("chai").expect
  8. _ = require("lodash")
  9. # These tests are neither acceptance tests nor unit tests. It's difficult to
  10. # test/verify that our locking is doing what we hope.
  11. # These tests call methods in ProjectGetter and ProjectEntityMongoUpdateHandler
  12. # to see that they DO NOT work when a lock has been taken.
  13. #
  14. # It is tested that these methods DO work when the lock has not been taken in
  15. # other acceptance tests.
  16. describe "ProjectStructureMongoLock", ->
  17. describe "whilst a project lock is taken", ->
  18. before (done) ->
  19. # We want to instantly fail if the lock is taken
  20. LockManager.MAX_LOCK_WAIT_TIME = 1
  21. @lockValue = "lock-value"
  22. userDetails =
  23. holdingAccount:false,
  24. email: 'test@example.com'
  25. UserCreator.createNewUser userDetails, (err, user) =>
  26. @user = user
  27. throw err if err?
  28. ProjectCreationHandler.createBlankProject user._id, 'locked-project', (err, project) =>
  29. throw err if err?
  30. @locked_project = project
  31. namespace = ProjectEntityMongoUpdateHandler.LOCK_NAMESPACE
  32. @lock_key = "lock:web:#{namespace}:#{project._id}"
  33. LockManager._getLock @lock_key, namespace, (err, lockValue) =>
  34. @lockValue = lockValue
  35. done()
  36. return
  37. after (done) ->
  38. LockManager._releaseLock @lock_key, @lockValue, done
  39. describe 'interacting with the locked project', ->
  40. LOCKING_UPDATE_METHODS = ['addDoc', 'addFile', 'mkdirp', 'moveEntity', 'renameEntity', 'addFolder']
  41. for methodName in LOCKING_UPDATE_METHODS
  42. it "cannot call ProjectEntityMongoUpdateHandler.#{methodName}", (done) ->
  43. method = ProjectEntityMongoUpdateHandler[methodName]
  44. args = _.times(method.length - 2, _.constant(null))
  45. method @locked_project._id, args, (err) ->
  46. expect(err).to.deep.equal new Error("Timeout")
  47. done()
  48. it "cannot get the project without a projection", (done) ->
  49. ProjectGetter.getProject @locked_project._id, (err) ->
  50. expect(err).to.deep.equal new Error("Timeout")
  51. done()
  52. it "cannot get the project if rootFolder is in the projection", (done) ->
  53. ProjectGetter.getProject @locked_project._id, rootFolder: true, (err) ->
  54. expect(err).to.deep.equal new Error("Timeout")
  55. done()
  56. it "can get the project if rootFolder is not in the projection", (done) ->
  57. ProjectGetter.getProject @locked_project._id, _id: true, (err, project) =>
  58. expect(err).to.equal(null)
  59. expect(project._id).to.deep.equal(@locked_project._id)
  60. done()
  61. describe 'interacting with other projects', ->
  62. before (done) ->
  63. ProjectCreationHandler.createBlankProject @user._id, 'unlocked-project', (err, project) =>
  64. throw err if err?
  65. @unlocked_project = project
  66. done()
  67. it "can add folders to other projects", (done) ->
  68. ProjectEntityMongoUpdateHandler.addFolder @unlocked_project._id, @unlocked_project.rootFolder[0]._id, 'new folder', (err, folder) ->
  69. expect(err).to.equal(null)
  70. expect(folder).to.be.defined
  71. done()
  72. it "can get other projects without a projection", (done) ->
  73. ProjectGetter.getProject @unlocked_project._id, (err, project) =>
  74. expect(err).to.equal(null)
  75. expect(project._id).to.deep.equal(@unlocked_project._id)
  76. done()