Example #1
0
    def testModelSaveHooks(self):
        """
        This tests the general correctness of the model save hooks
        """

        def preSave(event):
            count["pre"] += 1

        def createdSave(event):
            count["created"] += 1

        def postSave(event):
            count["post"] += 1

        count = collections.defaultdict(int)
        with events.bound("model.user.save.created", "test", createdSave):
            user = self.model("user").createUser(
                login="******", password="******", firstName="A", lastName="A", email="*****@*****.**"
            )
            self.assertEqual(count["created"], 1)

            count = collections.defaultdict(int)
            with events.bound("model.user.save", "test", preSave), events.bound(
                "model.user.save.after", "test", postSave
            ):
                user = self.model("user").save(user, triggerEvents=False)
                self.assertEqual(count["pre"], 0)
                self.assertEqual(count["created"], 0)
                self.assertEqual(count["post"], 0)

                count = collections.defaultdict(int)
                self.model("user").save(user)
                self.assertEqual(count["pre"], 1)
                self.assertEqual(count["created"], 0)
                self.assertEqual(count["post"], 1)
Example #2
0
    def testModelSaveHooks(self):
        """
        This tests the general correctness of the model save hooks
        """
        def preSave(event):
            count['pre'] += 1

        def createdSave(event):
            count['created'] += 1

        def postSave(event):
            count['post'] += 1

        count = collections.defaultdict(int)
        with events.bound('model.user.save.created', 'test', createdSave):
            user = User().createUser(login='******',
                                     password='******',
                                     firstName='A',
                                     lastName='A',
                                     email='*****@*****.**')
            self.assertEqual(count['created'], 1)

            count = collections.defaultdict(int)
            with events.bound('model.user.save', 'test', preSave), \
                    events.bound('model.user.save.after', 'test', postSave):
                user = User().save(user, triggerEvents=False)
                self.assertEqual(count['pre'], 0)
                self.assertEqual(count['created'], 0)
                self.assertEqual(count['post'], 0)

                count = collections.defaultdict(int)
                User().save(user)
                self.assertEqual(count['pre'], 1)
                self.assertEqual(count['created'], 0)
                self.assertEqual(count['post'], 1)
Example #3
0
    def testModelSaveHooks(self):
        """
        This tests the general correctness of the model save hooks
        """
        def preSave(event):
            count['pre'] += 1

        def createdSave(event):
            count['created'] += 1

        def postSave(event):
            count['post'] += 1

        count = collections.defaultdict(int)
        with events.bound('model.user.save.created', 'test', createdSave):
            user = User().createUser(
                login='******', password='******', firstName='A', lastName='A',
                email='*****@*****.**')
            self.assertEqual(count['created'], 1)

            count = collections.defaultdict(int)
            with events.bound('model.user.save', 'test', preSave), \
                    events.bound('model.user.save.after', 'test', postSave):
                user = User().save(user, triggerEvents=False)
                self.assertEqual(count['pre'], 0)
                self.assertEqual(count['created'], 0)
                self.assertEqual(count['post'], 0)

                count = collections.defaultdict(int)
                User().save(user)
                self.assertEqual(count['pre'], 1)
                self.assertEqual(count['created'], 0)
                self.assertEqual(count['post'], 1)
Example #4
0
    def testValidateCustomStrStatus(self):
        job = self.jobModel.createJob(title='test',
                                      type='x',
                                      user=self.users[0])

        def validateStatus(event):
            states = ['a', 'b', 'c']

            if event.info in states:
                event.preventDefault().addResponse(True)

        def validTransitions(event):
            if event.info['status'] == 'a':
                event.preventDefault().addResponse([JobStatus.INACTIVE])

        with self.assertRaises(ValidationException):
            self.jobModel.updateJob(job, status='a')

        with events.bound('jobs.status.validate', 'test', validateStatus), \
                events.bound('jobs.status.validTransitions', 'test', validTransitions):
            self.jobModel.updateJob(job, status='a')
            self.assertEqual(job['status'], 'a')

        with self.assertRaises(ValidationException), \
                events.bound('jobs.status.validate', 'test', validateStatus):
            self.jobModel.updateJob(job, status='foo')
Example #5
0
    def testValidateCustomStrStatus(self):
        jobModel = self.model('job', 'jobs')
        job = jobModel.createJob(title='test', type='x', user=self.users[0])

        def validateStatus(event):
            states = ['a', 'b', 'c']

            if event.info in states:
                event.preventDefault().addResponse(True)

        def validTransitions(event):
            if event.info['status'] == 'a':
                event.preventDefault().addResponse([JobStatus.INACTIVE])

        with self.assertRaises(ValidationException):
            jobModel.updateJob(job, status='a')

        with events.bound('jobs.status.validate', 'test', validateStatus), \
                events.bound('jobs.status.validTransitions', 'test', validTransitions):
            jobModel.updateJob(job, status='a')
            self.assertEqual(job['status'], 'a')

        with self.assertRaises(ValidationException), \
                events.bound('jobs.status.validate', 'test', validateStatus):
            jobModel.updateJob(job, status='foo')
Example #6
0
    def testDeleteFolder(self):
        cbInfo = {}

        # Hook into model deletion with kwargs event to test it
        def cb(event):
            cbInfo["kwargs"] = event.info["kwargs"]
            cbInfo["doc"] = event.info["document"]

        with events.bound("model.folder.remove_with_kwargs", "test", cb):

            # Requesting with no path should fail
            resp = self.request(path="/folder", method="DELETE", user=self.admin)
            self.assertStatus(resp, 400)

            # Grab one of the user's top level folders
            folders = self.model("folder").childFolders(
                parent=self.admin, parentType="user", user=self.admin, limit=1, sort=[("name", SortDir.DESCENDING)]
            )
            folderResp = six.next(folders)

            # Add a subfolder and an item to that folder
            subfolder = self.model("folder").createFolder(folderResp, "sub", parentType="folder", creator=self.admin)
            item = self.model("item").createItem("item", creator=self.admin, folder=subfolder)

            self.assertTrue("_id" in subfolder)
            self.assertTrue("_id" in item)

            # Delete the folder
            resp = self.request(
                path="/folder/%s" % folderResp["_id"], method="DELETE", user=self.admin, params={"progress": "true"}
            )
            self.assertStatusOk(resp)

            # Make sure the folder, its subfolder, and its item were all deleted
            folder = self.model("folder").load(folderResp["_id"], force=True)
            subfolder = self.model("folder").load(subfolder["_id"], force=True)
            item = self.model("item").load(item["_id"])

            self.assertEqual(folder, None)
            self.assertEqual(subfolder, None)
            self.assertEqual(item, None)

            # Make sure progress record exists and that it is set to expire soon
            notifs = list(self.model("notification").get(self.admin))
            self.assertEqual(len(notifs), 1)
            self.assertEqual(notifs[0]["type"], "progress")
            self.assertEqual(notifs[0]["data"]["state"], ProgressState.SUCCESS)
            self.assertEqual(notifs[0]["data"]["title"], "Deleting folder Public")
            self.assertEqual(notifs[0]["data"]["message"], "Done")
            self.assertEqual(notifs[0]["data"]["total"], 3)
            self.assertEqual(notifs[0]["data"]["current"], 3)
            self.assertTrue(notifs[0]["expires"] < datetime.datetime.utcnow() + datetime.timedelta(minutes=1))

            # Make sure our event handler was called with expected args
            self.assertTrue("kwargs" in cbInfo)
            self.assertTrue("doc" in cbInfo)
            self.assertTrue("progress" in cbInfo["kwargs"])
            self.assertEqual(cbInfo["doc"]["_id"], folderResp["_id"])
Example #7
0
    def testSynchronousEvents(self):
        name, failname = '_test.event', '_test.failure'
        handlerName = '_test.handler'
        with events.bound(name, handlerName, self._increment), \
                events.bound(failname, handlerName, self._raiseException):
            # Make sure our exception propagates out of the handler
            try:
                events.trigger(failname)
                self.assertTrue(False)
            except Exception as e:
                self.assertEqual(e.args[0], 'Failure condition')

            # Bind an event to increment the counter
            self.assertEqual(self.ctr, 0)
            event = events.trigger(name, {'amount': 2})
            self.assertEqual(self.ctr, 2)
            self.assertTrue(event.propagate)
            self.assertFalse(event.defaultPrevented)
            self.assertEqual(event.responses, [])

            # The event should still be bound here if another handler unbinds
            events.unbind(name, 'not the handler name')
            events.trigger(name, {'amount': 2})
            self.assertEqual(self.ctr, 4)

        # Actually unbind the event, by going out of scope of "bound"
        events.trigger(name, {'amount': 2})
        self.assertEqual(self.ctr, 4)

        # Bind an event that prevents the default action and passes a response
        with events.bound(name, handlerName, self._eatEvent), \
                events.bound(name, 'other handler name',
                             self._shouldNotBeCalled):
            event = events.trigger(name)
            self.assertTrue(event.defaultPrevented)
            self.assertFalse(event.propagate)
            self.assertEqual(event.responses, [{'foo': 'bar'}])

        # Test that the context manager unbinds after an unhandled exception
        try:
            with events.bound(failname, handlerName, self._raiseException):
                events.trigger(failname)
        except Exception:
            # The event should should be unbound at this point
            events.trigger(failname)
Example #8
0
    def testSynchronousEvents(self):
        name, failname = '_test.event', '_test.failure'
        handlerName = '_test.handler'
        with events.bound(name, handlerName, self._increment), \
                events.bound(failname, handlerName, self._raiseException):
            # Make sure our exception propagates out of the handler
            try:
                events.trigger(failname)
                self.assertTrue(False)
            except Exception as e:
                self.assertEqual(e.args[0], 'Failure condition')

            # Bind an event to increment the counter
            self.assertEqual(self.ctr, 0)
            event = events.trigger(name, {'amount': 2})
            self.assertEqual(self.ctr, 2)
            self.assertTrue(event.propagate)
            self.assertFalse(event.defaultPrevented)
            self.assertEqual(event.responses, [])

            # The event should still be bound here if another handler unbinds
            events.unbind(name, 'not the handler name')
            events.trigger(name, {'amount': 2})
            self.assertEqual(self.ctr, 4)

        # Actually unbind the event, by going out of scope of "bound"
        events.trigger(name, {'amount': 2})
        self.assertEqual(self.ctr, 4)

        # Bind an event that prevents the default action and passes a response
        with events.bound(name, handlerName, self._eatEvent), \
                events.bound(name, 'other handler name',
                             self._shouldNotBeCalled):
            event = events.trigger(name)
            self.assertTrue(event.defaultPrevented)
            self.assertFalse(event.propagate)
            self.assertEqual(event.responses, [{'foo': 'bar'}])

        # Test that the context manager unbinds after an unhandled exception
        try:
            with events.bound(failname, handlerName, self._raiseException):
                events.trigger(failname)
        except Exception:
            # The event should should be unbound at this point
            events.trigger(failname)
Example #9
0
    def _testUploadReference(self):
        eventList = []

        def processEvent(event):
            eventList.append(event.info)

        with events.bound('model.file.finalizeUpload.after', 'lib_test', processEvent):
            path = os.path.join(self.libTestDir, 'sub0', 'f')
            size = os.path.getsize(path)
            with open(path) as fh:
                self.client.uploadFile(
                    self.publicFolder['_id'], fh, name='test1', size=size, parentType='folder',
                    reference='test1_reference')
            self.assertEqual(len(eventList), 1)
            self.assertEqual(eventList[0]['upload']['reference'], 'test1_reference')

            self.client.uploadFileToItem(str(eventList[0]['file']['itemId']), path,
                                         reference='test2_reference')
            self.assertEqual(len(eventList), 2)
            self.assertEqual(eventList[1]['upload']['reference'], 'test2_reference')
            self.assertNotEqual(eventList[0]['file']['_id'],
                                eventList[1]['file']['_id'])

            with open(path, 'ab') as fh:
                fh.write(b'test')

            size = os.path.getsize(path)
            self.client.uploadFileToItem(str(eventList[0]['file']['itemId']), path,
                                         reference='test3_reference')
            self.assertEqual(len(eventList), 3)
            self.assertEqual(eventList[2]['upload']['reference'], 'test3_reference')
            self.assertNotEqual(eventList[0]['file']['_id'],
                                eventList[2]['file']['_id'])
            self.assertEqual(eventList[1]['file']['_id'],
                             eventList[2]['file']['_id'])

            item = self.client.createItem(self.publicFolder['_id'], 'a second item')
            # Test explicit MIME type setting
            file = self.client.uploadFileToItem(item['_id'], path,
                                                mimeType='image/jpeg')
            self.assertEqual(file['mimeType'], 'image/jpeg')

            # Test guessing of MIME type
            testPath = os.path.join(self.libTestDir, 'out.txt')
            with open(testPath, 'w') as fh:
                fh.write('test')

            file = self.client.uploadFileToItem(item['_id'], testPath)
            self.assertEqual(file['mimeType'], 'text/plain')

            # Test uploading to a folder
            self.client.uploadFileToFolder(
                str(self.publicFolder['_id']), path, reference='test4_reference')
            self.assertEqual(len(eventList), 6)
            self.assertEqual(eventList[-1]['upload']['reference'], 'test4_reference')
            self.assertNotEqual(eventList[2]['file']['_id'],
                                eventList[-1]['file']['_id'])
Example #10
0
    def testUploadReference(self):
        eventList = []

        def processEvent(event):
            eventList.append(event.info)

        with events.bound('model.file.finalizeUpload.after', 'lib_test', processEvent):
            path = os.path.join(self.libTestDir, 'sub0', 'f')
            size = os.path.getsize(path)
            with open(path) as fh:
                self.client.uploadFile(
                    self.publicFolder['_id'], fh, name='test1', size=size, parentType='folder',
                    reference='test1_reference')
            self.assertEqual(len(eventList), 1)
            self.assertEqual(eventList[0]['upload']['reference'], 'test1_reference')

            self.client.uploadFileToItem(str(eventList[0]['file']['itemId']), path,
                                         reference='test2_reference')
            self.assertEqual(len(eventList), 2)
            self.assertEqual(eventList[1]['upload']['reference'], 'test2_reference')
            self.assertNotEqual(eventList[0]['file']['_id'],
                                eventList[1]['file']['_id'])

            with open(path, 'ab') as fh:
                fh.write(b'test')

            self.client.uploadFileToItem(str(eventList[0]['file']['itemId']), path,
                                         reference='test3_reference')
            self.assertEqual(len(eventList), 3)
            self.assertEqual(eventList[2]['upload']['reference'], 'test3_reference')
            self.assertNotEqual(eventList[0]['file']['_id'],
                                eventList[2]['file']['_id'])
            self.assertEqual(eventList[1]['file']['_id'],
                             eventList[2]['file']['_id'])

            item = self.client.createItem(self.publicFolder['_id'], 'a second item')
            # Test explicit MIME type setting
            file = self.client.uploadFileToItem(item['_id'], path,
                                                mimeType='image/jpeg')
            self.assertEqual(file['mimeType'], 'image/jpeg')

            # Test guessing of MIME type
            testPath = os.path.join(self.libTestDir, 'out.txt')
            with open(testPath, 'w') as fh:
                fh.write('test')

            file = self.client.uploadFileToItem(item['_id'], testPath)
            self.assertEqual(file['mimeType'], 'text/plain')

            # Test uploading to a folder
            self.client.uploadFileToFolder(
                str(self.publicFolder['_id']), path, reference='test4_reference')
            self.assertEqual(len(eventList), 6)
            self.assertEqual(eventList[-1]['upload']['reference'], 'test4_reference')
            self.assertNotEqual(eventList[2]['file']['_id'],
                                eventList[-1]['file']['_id'])
Example #11
0
def testSynchronousEvents(eventsHelper):
    name, failname = '_test.event', '_test.failure'
    handlerName = '_test.handler'
    with events.bound(name, handlerName, eventsHelper._increment), \
            events.bound(failname, handlerName, eventsHelper._raiseException):
        # Make sure our exception propagates out of the handler
        with pytest.raises(Exception, match='^Failure condition$'):
            events.trigger(failname)

        # Bind an event to increment the counter
        assert eventsHelper.ctr == 0
        event = events.trigger(name, {'amount': 2})
        assert eventsHelper.ctr == 2
        assert event.propagate
        assert not event.defaultPrevented
        assert event.responses == []

        # The event should still be bound here if another handler unbinds
        events.unbind(name, 'not the handler name')
        events.trigger(name, {'amount': 2})
        assert eventsHelper.ctr == 4

    # Actually unbind the event, by going out of scope of "bound"
    events.trigger(name, {'amount': 2})
    assert eventsHelper.ctr == 4

    # Bind an event that prevents the default action and passes a response
    with events.bound(name, handlerName, eventsHelper._eatEvent), \
            events.bound(name, 'other handler name',
                         eventsHelper._shouldNotBeCalled):
        event = events.trigger(name)
        assert event.defaultPrevented
        assert not event.propagate
        assert event.responses == [{'foo': 'bar'}]

    # Test that the context manager unbinds after an unhandled exception
    try:
        with events.bound(failname, handlerName, eventsHelper._raiseException):
            events.trigger(failname)
    except Exception:
        # The event should should be unbound at this point
        events.trigger(failname)
Example #12
0
def testSynchronousEvents(eventsHelper):
    name, failname = '_test.event', '_test.failure'
    handlerName = '_test.handler'
    with events.bound(name, handlerName, eventsHelper._increment), \
            events.bound(failname, handlerName, eventsHelper._raiseException):
        # Make sure our exception propagates out of the handler
        with pytest.raises(Exception, match='^Failure condition$'):
            events.trigger(failname)

        # Bind an event to increment the counter
        assert eventsHelper.ctr == 0
        event = events.trigger(name, {'amount': 2})
        assert eventsHelper.ctr == 2
        assert event.propagate
        assert not event.defaultPrevented
        assert event.responses == []

        # The event should still be bound here if another handler unbinds
        events.unbind(name, 'not the handler name')
        events.trigger(name, {'amount': 2})
        assert eventsHelper.ctr == 4

    # Actually unbind the event, by going out of scope of "bound"
    events.trigger(name, {'amount': 2})
    assert eventsHelper.ctr == 4

    # Bind an event that prevents the default action and passes a response
    with events.bound(name, handlerName, eventsHelper._eatEvent), \
            events.bound(name, 'other handler name',
                         eventsHelper._shouldNotBeCalled):
        event = events.trigger(name)
        assert event.defaultPrevented
        assert not event.propagate
        assert event.responses == [{'foo': 'bar'}]

    # Test that the context manager unbinds after an unhandled exception
    try:
        with events.bound(failname, handlerName, eventsHelper._raiseException):
            events.trigger(failname)
    except Exception:
        # The event should should be unbound at this point
        events.trigger(failname)
Example #13
0
    def testValidateCustomStatus(self):
        job = self.jobModel.createJob(title='test', type='x', user=self.users[0])

        def validateStatus(event):
            if event.info == 1234:
                event.preventDefault().addResponse(True)

        def validTransitions(event):
            if event.info['status'] == 1234:
                event.preventDefault().addResponse([JobStatus.INACTIVE])

        with self.assertRaises(ValidationException):
            self.jobModel.updateJob(job, status=1234)  # Should fail

        with events.bound('jobs.status.validate', 'test', validateStatus), \
                events.bound('jobs.status.validTransitions', 'test', validTransitions):
            self.jobModel.updateJob(job, status=1234)  # Should work

            with self.assertRaises(ValidationException):
                self.jobModel.updateJob(job, status=4321)  # Should fail
Example #14
0
    def testValidateCustomStatus(self):
        job = self.jobModel.createJob(title='test', type='x', user=self.users[0])

        def validateStatus(event):
            if event.info == 1234:
                event.preventDefault().addResponse(True)

        def validTransitions(event):
            if event.info['status'] == 1234:
                event.preventDefault().addResponse([JobStatus.INACTIVE])

        with self.assertRaises(ValidationException):
            self.jobModel.updateJob(job, status=1234)  # Should fail

        with events.bound('jobs.status.validate', 'test', validateStatus), \
                events.bound('jobs.status.validTransitions', 'test', validTransitions):
            self.jobModel.updateJob(job, status=1234)  # Should work

            with self.assertRaises(ValidationException):
                self.jobModel.updateJob(job, status=4321)  # Should fail
Example #15
0
def testForegroundDaemon(eventsHelper):
    assert isinstance(events.daemon, events.ForegroundEventsDaemon)

    # Should still be able to call start
    events.daemon.start()

    def callback(event):
        eventsHelper.ctr += 1
        eventsHelper.responses = event.responses

    with events.bound('_test.event',  '_test.handler', eventsHelper._raiseException):
        with pytest.raises(Exception, match='^Failure condition$'):
            events.daemon.trigger('_test.event', None, callback)

    with events.bound('_test.event',  '_test.handler', eventsHelper._incrementWithResponse):
        events.daemon.trigger('_test.event', {'amount': 2}, callback)

    assert eventsHelper.ctr == 3
    assert eventsHelper.responses == ['foo']

    events.daemon.stop()
Example #16
0
    def testJobSaveEventModification(self):
        def customSave(event):
            kwargs = json_util.loads(event.info['kwargs'])
            kwargs['key2'] = 'newvalue'
            event.info['kwargs'] = json_util.dumps(kwargs)

        job = self.jobModel.createJob(title='A job', type='t', user=self.users[1], public=True)

        job['kwargs'] = {'key1': 'value1', 'key2': 'value2'}
        with events.bound('model.job.save', 'test', customSave):
            job = self.jobModel.save(job)
            self.assertEqual(job['kwargs']['key2'], 'newvalue')
Example #17
0
def testForegroundDaemon(eventsHelper):
    assert isinstance(events.daemon, events.ForegroundEventsDaemon)

    # Should still be able to call start
    events.daemon.start()

    def callback(event):
        eventsHelper.ctr += 1
        eventsHelper.responses = event.responses

    with events.bound('_test.event', '_test.handler', eventsHelper._raiseException):
        with pytest.raises(Exception, match='^Failure condition$'):
            events.daemon.trigger('_test.event', None, callback)

    with events.bound('_test.event', '_test.handler', eventsHelper._incrementWithResponse):
        events.daemon.trigger('_test.event', {'amount': 2}, callback)

    assert eventsHelper.ctr == 3
    assert eventsHelper.responses == ['foo']

    events.daemon.stop()
Example #18
0
    def testJobSaveEventModification(self):
        def customSave(event):
            kwargs = json_util.loads(event.info['kwargs'])
            kwargs['key2'] = 'newvalue'
            event.info['kwargs'] = json_util.dumps(kwargs)

        job = self.jobModel.createJob(title='A job', type='t', user=self.users[1], public=True)

        job['kwargs'] = {'key1': 'value1', 'key2': 'value2'}
        with events.bound('model.job.save', 'test', customSave):
            job = self.jobModel.save(job)
            self.assertEqual(job['kwargs']['key2'], 'newvalue')
Example #19
0
    def testForegroundDaemon(self):
        self.assertIsInstance(events.daemon, events.ForegroundEventsDaemon)

        # Should still be able to call start
        events.daemon.start()

        def callback(event):
            self.ctr += 1
            self.responses = event.responses

        with events.bound('_test.event',  '_test.handler', self._raiseException):
            with six.assertRaisesRegex(self, Exception, 'Failure condition'):
                events.daemon.trigger('_test.event', None, callback)

        with events.bound('_test.event',  '_test.handler', self._incrementWithResponse):
            events.daemon.trigger('_test.event', {'amount': 2}, callback)

        self.assertEqual(self.ctr, 3)
        self.assertEqual(self.responses, ['foo'])

        events.daemon.stop()
Example #20
0
def testAsyncEvents(eventsHelper):
    name, failname = '_test.event', '_test.failure'
    handlerName = '_test.handler'

    def callback(event):
        eventsHelper.ctr += 1
        eventsHelper.responses = event.responses

    with events.bound(failname, handlerName, eventsHelper._raiseException), \
            events.bound(name, handlerName, eventsHelper._incrementWithResponse):
        # Make sure an async handler that fails does not break the event
        # loop and that its callback is not triggered.
        assert events.daemon.eventQueue.qsize() == 0
        events.daemon.trigger(failname, handlerName, callback)

        # Triggering the event before the daemon starts should do nothing
        assert events.daemon.eventQueue.qsize() == 1
        events.daemon.trigger(name, {'amount': 2}, callback)
        assert events.daemon.eventQueue.qsize() == 2
        assert eventsHelper.ctr == 0

        # Now run the asynchronous event handler, which should eventually
        # cause our counter to be incremented.
        events.daemon.start()
        # Ensure that all of our events have been started within a
        # reasonable amount of time.  Also check the results in the loop,
        # since the qsize only indicates if all events were started, not
        # finished.
        startTime = time.time()
        while True:
            if events.daemon.eventQueue.qsize() == 0:
                if eventsHelper.ctr == 3:
                    break
            if time.time() - startTime > 15:
                break
            time.sleep(0.1)
        assert events.daemon.eventQueue.qsize() == 0
        assert eventsHelper.ctr == 3
        assert eventsHelper.responses == ['foo']
        events.daemon.stop()
Example #21
0
    def testAsyncEvents(self):
        name, failname = '_test.event', '_test.failure'
        handlerName = '_test.handler'

        def callback(event):
            self.ctr += 1
            self.responses = event.responses

        with events.bound(failname, handlerName, self._raiseException), \
                events.bound(name, handlerName, self._incrementWithResponse):
            # Make sure an async handler that fails does not break the event
            # loop and that its callback is not triggered.
            self.assertEqual(events.daemon.eventQueue.qsize(), 0)
            events.daemon.trigger(failname, handlerName, callback)

            # Triggering the event before the daemon starts should do nothing
            self.assertEqual(events.daemon.eventQueue.qsize(), 1)
            events.daemon.trigger(name, {'amount': 2}, callback)
            self.assertEqual(events.daemon.eventQueue.qsize(), 2)
            self.assertEqual(self.ctr, 0)

            # Now run the asynchronous event handler, which should eventually
            # cause our counter to be incremented.
            events.daemon.start()
            # Ensure that all of our events have been started within a
            # reasonable amount of time.  Also check the results in the loop,
            # since the qsize only indicates if all events were started, not
            # finished.
            startTime = time.time()
            while True:
                if events.daemon.eventQueue.qsize() == 0:
                    if self.ctr == 3:
                        break
                if time.time() - startTime > 15:
                    break
                time.sleep(0.1)
            self.assertEqual(events.daemon.eventQueue.qsize(), 0)
            self.assertEqual(self.ctr, 3)
            self.assertEqual(self.responses, ['foo'])
            events.daemon.stop()
Example #22
0
    def testForegroundDaemon(self):
        self.assertIsInstance(events.daemon, events.ForegroundEventsDaemon)

        # Should still be able to call start
        events.daemon.start()

        def callback(event):
            self.ctr += 1
            self.responses = event.responses

        with events.bound('_test.event', '_test.handler',
                          self._raiseException):
            with six.assertRaisesRegex(self, Exception, 'Failure condition'):
                events.daemon.trigger('_test.event', None, callback)

        with events.bound('_test.event', '_test.handler',
                          self._incrementWithResponse):
            events.daemon.trigger('_test.event', {'amount': 2}, callback)

        self.assertEqual(self.ctr, 3)
        self.assertEqual(self.responses, ['foo'])

        events.daemon.stop()
Example #23
0
    def testValidateCustomStatus(self):
        jobModel = self.model('job', 'jobs')
        job = jobModel.createJob(title='test', type='x', user=self.users[0])

        def validateStatus(event):
            if event.info == 1234:
                event.preventDefault().addResponse(True)

        with self.assertRaises(ValidationException):
            jobModel.updateJob(job, status=1234)  # Should fail

        with events.bound('jobs.status.validate', 'test', validateStatus):
            jobModel.updateJob(job, status=1234)  # Should work

            with self.assertRaises(ValidationException):
                jobModel.updateJob(job, status=4321)  # Should fail
Example #24
0
    def testValidateCustomStatus(self):
        jobModel = self.model('job', 'jobs')
        job = jobModel.createJob(title='test', type='x', user=self.users[0])

        def validateStatus(event):
            if event.info == 1234:
                event.preventDefault().addResponse(True)

        with self.assertRaises(ValidationException):
            jobModel.updateJob(job, status=1234)  # Should fail

        with events.bound('jobs.status.validate', 'test', validateStatus):
            jobModel.updateJob(job, status=1234)  # Should work

            with self.assertRaises(ValidationException):
                jobModel.updateJob(job, status=4321)  # Should fail
Example #25
0
    def testDeleteFolder(self):
        cbInfo = {}

        # Hook into model deletion with kwargs event to test it
        def cb(event):
            cbInfo['kwargs'] = event.info['kwargs']
            cbInfo['doc'] = event.info['document']

        with events.bound('model.folder.remove_with_kwargs', 'test', cb):

            # Requesting with no path should fail
            resp = self.request(path='/folder', method='DELETE',
                                user=self.admin)
            self.assertStatus(resp, 400)

            # Grab one of the user's top level folders
            folders = self.model('folder').childFolders(
                parent=self.admin, parentType='user', user=self.admin, limit=1,
                sort=[('name', SortDir.DESCENDING)])
            folderResp = six.next(folders)

            # Add a subfolder and an item to that folder
            subfolder = self.model('folder').createFolder(
                folderResp, 'sub', parentType='folder', creator=self.admin)
            item = self.model('item').createItem(
                'item', creator=self.admin, folder=subfolder)

            self.assertTrue('_id' in subfolder)
            self.assertTrue('_id' in item)

            # Delete the folder
            resp = self.request(path='/folder/%s' % folderResp['_id'],
                                method='DELETE', user=self.admin, params={
                                    'progress': 'true'
            })
            self.assertStatusOk(resp)

            # Make sure the folder, its subfolder, and its item were all deleted
            folder = self.model('folder').load(folderResp['_id'], force=True)
            subfolder = self.model('folder').load(subfolder['_id'], force=True)
            item = self.model('item').load(item['_id'])

            self.assertEqual(folder, None)
            self.assertEqual(subfolder, None)
            self.assertEqual(item, None)

            # Make sure progress record exists and that it is set to expire soon
            notifs = list(self.model('notification').get(self.admin))
            self.assertEqual(len(notifs), 1)
            self.assertEqual(notifs[0]['type'], 'progress')
            self.assertEqual(notifs[0]['data']['state'], ProgressState.SUCCESS)
            self.assertEqual(notifs[0]['data']['title'],
                             'Deleting folder Public')
            self.assertEqual(notifs[0]['data']['message'], 'Done')
            self.assertEqual(notifs[0]['data']['total'], 3)
            self.assertEqual(notifs[0]['data']['current'], 3)
            self.assertTrue(notifs[0]['expires'] < datetime.datetime.utcnow() +
                            datetime.timedelta(minutes=1))

            # Make sure our event handler was called with expected args
            self.assertTrue('kwargs' in cbInfo)
            self.assertTrue('doc' in cbInfo)
            self.assertTrue('progress' in cbInfo['kwargs'])
            self.assertEqual(cbInfo['doc']['_id'], folderResp['_id'])
Example #26
0
    def testDeleteFolder(self):
        cbInfo = {}

        # Hook into model deletion with kwargs event to test it
        def cb(event):
            cbInfo['kwargs'] = event.info['kwargs']
            cbInfo['doc'] = event.info['document']

        with events.bound('model.folder.remove_with_kwargs', 'test', cb):

            # Requesting with no path should fail
            resp = self.request(path='/folder',
                                method='DELETE',
                                user=self.admin)
            self.assertStatus(resp, 400)

            # Grab one of the user's top level folders
            folders = self.model('folder').childFolders(
                parent=self.admin,
                parentType='user',
                user=self.admin,
                limit=1,
                sort=[('name', SortDir.DESCENDING)])
            folderResp = six.next(folders)

            # Add a subfolder and an item to that folder
            subfolder = self.model('folder').createFolder(folderResp,
                                                          'sub',
                                                          parentType='folder',
                                                          creator=self.admin)
            item = self.model('item').createItem('item',
                                                 creator=self.admin,
                                                 folder=subfolder)

            self.assertTrue('_id' in subfolder)
            self.assertTrue('_id' in item)

            # Delete the folder
            resp = self.request(path='/folder/%s' % folderResp['_id'],
                                method='DELETE',
                                user=self.admin,
                                params={'progress': 'true'})
            self.assertStatusOk(resp)

            # Make sure the folder, its subfolder, and its item were all deleted
            folder = self.model('folder').load(folderResp['_id'], force=True)
            subfolder = self.model('folder').load(subfolder['_id'], force=True)
            item = self.model('item').load(item['_id'])

            self.assertEqual(folder, None)
            self.assertEqual(subfolder, None)
            self.assertEqual(item, None)

            # Make sure progress record exists and that it is set to expire soon
            notifs = list(self.model('notification').get(self.admin))
            self.assertEqual(len(notifs), 1)
            self.assertEqual(notifs[0]['type'], 'progress')
            self.assertEqual(notifs[0]['data']['state'], ProgressState.SUCCESS)
            self.assertEqual(notifs[0]['data']['title'],
                             'Deleting folder Public')
            self.assertEqual(notifs[0]['data']['message'], 'Done')
            self.assertEqual(notifs[0]['data']['total'], 3)
            self.assertEqual(notifs[0]['data']['current'], 3)
            self.assertTrue(notifs[0]['expires'] < datetime.datetime.utcnow() +
                            datetime.timedelta(minutes=1))

            # Make sure our event handler was called with expected args
            self.assertTrue('kwargs' in cbInfo)
            self.assertTrue('doc' in cbInfo)
            self.assertTrue('progress' in cbInfo['kwargs'])
            self.assertEqual(cbInfo['doc']['_id'], folderResp['_id'])