~launchpad-pqm/launchpad/devel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
BugWatchActivity
================

The activity on a given bug watch is recorded in the BugWatchActivity
table.

We can create a new BugWatchActivity record for a bug watch using that
BugWatch's addActivity() method.

    >>> from lp.services.config import config
    >>> from lp.services.database.lpstorm import IStore
    >>> from lp.testing.layers import LaunchpadZopelessLayer
    >>> from lp.bugs.model.bugwatch import BugWatchActivity

In order to create a BugWatch to test with we need to switch DB users.
This is because the checkwatches DB user can't create BugWatches, whilst
at the same time _only_ the checkwatches DB user can create
BugWatchActivity instances.

    >>> LaunchpadZopelessLayer.switchDbUser('launchpad')
    >>> bug_watch = factory.makeBugWatch(remote_bug='42')

    >>> # This commit is unavoidable, otherwise we lose the watch when we
    >>> # switch users.
    >>> transaction.commit()
    >>> LaunchpadZopelessLayer.switchDbUser(config.checkwatches.dbuser)

When a BugWatch is first created there has been no activity on it.

    >>> print bug_watch.activity.count()
    0

    >>> bug_watch.addActivity()
    >>> store = IStore(BugWatchActivity)
    >>> store.flush()

We can access the BugWatchActivity record by looking at the BugWatch's
activity property.

    >>> print bug_watch.activity.count()
    1

    >>> activity = bug_watch.activity.first()
    >>> activity.bug_watch == bug_watch
    True

The BugWatchActivity's activity_date will be set automatically when it
is written to the database.

    >>> activity.activity_date
    datetime.datetime...

The BugWatchActivity's result will be BugWatchActivityStatus.SYNC_SUCCEEDED.

    >>> print activity.result.title
    Synchronisation succeeded

The other fields on the BugWatchActivity record, which aren't required,
will all be None.

    >>> print activity.message
    None
    >>> print activity.oops_id
    None


Recording BugWatch updates as BugWatchActivity
-----------------------------------------------

Whenever an update is made to a BugWatch that update is recorded as a
BugWatchActivity entry.

We can demonstrate this by passing our bug watch to
CheckwatchesMaster.updateBugWatches().

    >>> from lp.services.log.logger import BufferLogger
    >>> from lp.bugs.scripts.checkwatches import CheckwatchesMaster
    >>> from lp.bugs.tests.externalbugtracker import TestExternalBugTracker
    >>> updater = CheckwatchesMaster(transaction, BufferLogger())
    >>> updater.updateBugWatches(
    ...     TestExternalBugTracker('http://example.com'), [bug_watch])

An extra activity item will have been added to the BugWatch's activity
property.

    >>> print bug_watch.activity.count()
    2

The most recent activity entry will have a result of
BugWatchActivityStatus.SYNC_SUCCEEDED since it was
successful.

    >>> most_recent_activity = bug_watch.activity.first()
    >>> print most_recent_activity.result.title
    Synchronisation succeeded

Its message will also be empty

    >>> print most_recent_activity.message
    None

As will its oops_id

    >>> print most_recent_activity.oops_id
    None

If the remote bug tracker breaks during an update the error will be
recorded in the activity entry for that update.

    >>> from lp.bugs.externalbugtracker.base import UnparsableBugData
    >>> from lp.bugs.tests.externalbugtracker import (
    ...     TestBrokenExternalBugTracker)
    >>> broken_bugtracker = TestBrokenExternalBugTracker('http://example.com')
    >>> broken_bugtracker.get_remote_status_error = UnparsableBugData

    >>> updater.updateBugWatches(broken_bugtracker, [bug_watch])

Another entry will have been added to the watch's activity property.

    >>> print bug_watch.activity.count()
    3

And this time its result field will record that the the remote bug was
not found.

    >>> most_recent_activity = bug_watch.activity.first()
    >>> print most_recent_activity.result.title
    Unparsable Bug

The OOPS ID for the error will also have been recorded.

    >>> print most_recent_activity.oops_id
    OOPS...

The CheckwatchesMaster also adds BugWatchActivity entries when errors occur
that don't have an entry in the BugWatchActivityStatus DB Enum.

    >>> broken_bugtracker.get_remote_status_error = Exception
    >>> updater.updateBugWatches(broken_bugtracker, [bug_watch])
    >>> most_recent_activity = bug_watch.activity.first()

    >>> print most_recent_activity.result.title
    Unknown

The OOPS ID of the error is recorded so that we can debug it.

    >>> print most_recent_activity.oops_id
    OOPS...