##// END OF EJS Templates
events: use context manager for testing fired events
dan -
r376:ce1a3e78 default
parent child Browse files
Show More
@@ -1,49 +1,51 b''
1 1 # Copyright (C) 2016-2016 RhodeCode GmbH
2 2 #
3 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
5 5 # (only), as published by the Free Software Foundation.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU Affero General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 #
15 15 # This program is dual-licensed. If you wish to learn more about the
16 16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 18
19 19 from pyramid.threadlocal import get_current_registry
20 20
21 21
22 22 class RhodecodeEvent(object):
23 23 """
24 24 Base event class for all Rhodecode events
25 25 """
26 26
27 27
28 28 def trigger(event):
29 29 """
30 30 Helper method to send an event. This wraps the pyramid logic to send an
31 31 event.
32 32 """
33 33 # For the first step we are using pyramids thread locals here. If the
34 34 # event mechanism works out as a good solution we should think about
35 35 # passing the registry as an argument to get rid of it.
36 36 registry = get_current_registry()
37 37 registry.notify(event)
38 38
39 39
40 40 from rhodecode.events.user import (
41 UserPreCreate, UserPreUpdate, UserRegistered
41 UserPreCreate,
42 UserPreUpdate,
43 UserRegistered
42 44 )
43 45
44 46 from rhodecode.events.repo import (
45 47 RepoPreCreateEvent, RepoCreatedEvent,
46 48 RepoPreDeleteEvent, RepoDeletedEvent,
47 49 RepoPrePushEvent, RepoPushEvent,
48 50 RepoPrePullEvent, RepoPullEvent,
49 ) No newline at end of file
51 )
@@ -1,115 +1,113 b''
1 1 # Copyright (C) 2016-2016 RhodeCode GmbH
2 2 #
3 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
5 5 # (only), as published by the Free Software Foundation.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU Affero General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 #
15 15 # This program is dual-licensed. If you wish to learn more about the
16 16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 18
19 19 from rhodecode.model.db import Repository, Session
20 20 from rhodecode.events import RhodecodeEvent
21 21
22 22
23 23 class RepoEvent(RhodecodeEvent):
24 24 """
25 25 Base class for events acting on a repository.
26 26
27 27 :param repo: a :class:`Repository` instance
28 28 """
29 29 def __init__(self, repo):
30 30 self.repo = repo
31 31
32 32
33 33 class RepoPreCreateEvent(RepoEvent):
34 34 """
35 35 An instance of this class is emitted as an :term:`event` before a repo is
36 36 created.
37
38 :param repo_name: repository name
39 37 """
40 38 name = 'repo-pre-create'
41 39
42 40
43 41 class RepoCreatedEvent(RepoEvent):
44 42 """
45 43 An instance of this class is emitted as an :term:`event` whenever a repo is
46 44 created.
47 45 """
48 46 name = 'repo-created'
49 47
50 48
51 49 class RepoPreDeleteEvent(RepoEvent):
52 50 """
53 51 An instance of this class is emitted as an :term:`event` whenever a repo is
54 52 created.
55 53 """
56 54 name = 'repo-pre-delete'
57 55
58 56
59 57 class RepoDeletedEvent(RepoEvent):
60 58 """
61 59 An instance of this class is emitted as an :term:`event` whenever a repo is
62 60 created.
63 61 """
64 62 name = 'repo-deleted'
65 63
66 64
67 65 class RepoVCSEvent(RepoEvent):
68 66 """
69 67 Base class for events triggered by the VCS
70 68 """
71 69 def __init__(self, repo_name, extras):
72 70 self.repo = Repository.get_by_repo_name(repo_name)
73 71 if not self.repo:
74 72 raise Exception('repo by this name %s does not exist' % repo_name)
75 73 self.extras = extras
76 74 super(RepoVCSEvent, self).__init__(self.repo)
77 75
78 76
79 77 class RepoPrePullEvent(RepoVCSEvent):
80 78 """
81 79 An instance of this class is emitted as an :term:`event` before commits
82 80 are pulled from a repo.
83 81 """
84 82 name = 'repo-pre-pull'
85 83
86 84
87 85 class RepoPullEvent(RepoVCSEvent):
88 86 """
89 87 An instance of this class is emitted as an :term:`event` after commits
90 88 are pulled from a repo.
91 89 """
92 90 name = 'repo-pull'
93 91
94 92
95 93 class RepoPrePushEvent(RepoVCSEvent):
96 94 """
97 95 An instance of this class is emitted as an :term:`event` before commits
98 96 are pushed to a repo.
99 97 """
100 98 name = 'repo-pre-push'
101 99
102 100
103 101 class RepoPushEvent(RepoVCSEvent):
104 102 """
105 103 An instance of this class is emitted as an :term:`event` after commits
106 104 are pushed to a repo.
107 105
108 106 :param extras: (optional) dict of data from proxied VCS actions
109 107 """
110 108 name = 'repo-push'
111 109
112 110 def __init__(self, repo_name, pushed_commit_ids, extras):
113 111 super(RepoPushEvent, self).__init__(repo_name, extras)
114 112 self.pushed_commit_ids = pushed_commit_ids
115 113
@@ -1,38 +1,41 b''
1 1 # Copyright (C) 2016-2016 RhodeCode GmbH
2 2 #
3 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
5 5 # (only), as published by the Free Software Foundation.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU Affero General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 #
15 15 # This program is dual-licensed. If you wish to learn more about the
16 16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18 18
19 19 import mock
20 20 import decorator
21 21
22 22
23 def assert_fires_events(*expected_events):
24 """ Testing decorator to check if the function fires events in order """
25 def deco(func):
26 def wrapper(func, *args, **kwargs):
27 with mock.patch('rhodecode.events.trigger') as mock_trigger:
28 result = func(*args, **kwargs)
23 class EventCatcher(object):
24 """ Testing context manager to check if events are fired """
25
26 def __init__(self):
27 self.events = [] # the actual events captured
28 self.event_types = [] # the types of events captured
29 29
30 captured_events = []
31 for call in mock_trigger.call_args_list:
32 event = call[0][0]
33 captured_events.append(type(event))
30 def __enter__(self):
31 self.event_trigger_patch = mock.patch('rhodecode.events.trigger')
32 self.mocked_event_trigger = self.event_trigger_patch.start()
33 return self
34 34
35 assert set(captured_events) == set(expected_events)
36 return result
37 return decorator.decorator(wrapper, func)
38 return deco No newline at end of file
35 def __exit__(self, type_, value, traceback):
36 self.event_trigger_patch.stop()
37
38 for call in self.mocked_event_trigger.call_args_list:
39 event = call[0][0]
40 self.events.append(event)
41 self.event_types.append(type(event))
@@ -1,68 +1,79 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import pytest
22 22
23 from rhodecode.tests.events.conftest import assert_fires_events
23 from rhodecode.tests.events.conftest import EventCatcher
24 24
25 25 from rhodecode.lib import hooks_base, utils2
26 26 from rhodecode.model.repo import RepoModel
27 27 from rhodecode.events.repo import (
28 28 RepoPrePullEvent, RepoPullEvent,
29 29 RepoPrePushEvent, RepoPushEvent,
30 30 RepoPreCreateEvent, RepoCreatedEvent,
31 31 RepoPreDeleteEvent, RepoDeletedEvent,
32 32 )
33 33
34 34
35 35 @pytest.fixture
36 36 def scm_extras(user_regular, repo_stub):
37 37 extras = utils2.AttributeDict({
38 38 'ip': '127.0.0.1',
39 39 'username': user_regular.username,
40 40 'action': '',
41 41 'repository': repo_stub.repo_name,
42 42 'scm': repo_stub.scm_instance().alias,
43 43 'config': '',
44 44 'server_url': 'http://example.com',
45 45 'make_lock': None,
46 46 'locked_by': [None],
47 47 'commit_ids': ['a' * 40] * 3,
48 48 })
49 49 return extras
50 50
51 51
52 @assert_fires_events(
53 RepoPreCreateEvent, RepoCreatedEvent, RepoPreDeleteEvent, RepoDeletedEvent)
54 52 def test_create_delete_repo_fires_events(backend):
55 repo = backend.create_repo()
56 RepoModel().delete(repo)
53 with EventCatcher() as event_catcher:
54 repo = backend.create_repo()
55 assert event_catcher.event_types == [RepoPreCreateEvent, RepoCreatedEvent]
56
57 with EventCatcher() as event_catcher:
58 RepoModel().delete(repo)
59 assert event_catcher.event_types == [RepoPreDeleteEvent, RepoDeletedEvent]
57 60
58 61
59 @assert_fires_events(RepoPrePushEvent, RepoPushEvent)
60 62 def test_pull_fires_events(scm_extras):
61 hooks_base.pre_push(scm_extras)
62 hooks_base.post_push(scm_extras)
63 with EventCatcher() as event_catcher:
64 hooks_base.pre_push(scm_extras)
65 assert event_catcher.event_types == [RepoPrePushEvent]
66
67 with EventCatcher() as event_catcher:
68 hooks_base.post_push(scm_extras)
69 assert event_catcher.event_types == [RepoPushEvent]
63 70
64 71
65 @assert_fires_events(RepoPrePullEvent, RepoPullEvent)
66 72 def test_push_fires_events(scm_extras):
67 hooks_base.pre_pull(scm_extras)
68 hooks_base.post_pull(scm_extras)
73 with EventCatcher() as event_catcher:
74 hooks_base.pre_pull(scm_extras)
75 assert event_catcher.event_types == [RepoPrePullEvent]
76
77 with EventCatcher() as event_catcher:
78 hooks_base.post_pull(scm_extras)
79 assert event_catcher.event_types == [RepoPullEvent]
General Comments 0
You need to be logged in to leave comments. Login now