applied patch SF#1473939, initial Perforce support
[buildbot.git] / buildbot / test / test_p4poller.py
blob83b9582f0f87b05c367f8afb6cadb77979b58962
1 import sys
2 import time
4 from twisted.python import log, failure
5 from twisted.internet import defer
6 from twisted.trial import unittest
8 from buildbot.twcompat import maybeWait
9 from buildbot.changes.changes import Change
10 from buildbot.changes.p4poller import P4Source, get_simple_split
12 #log.startLogging(sys.stderr)
14 first_p4changes = \
15 """Change 1 on 2006/04/13 by slamb@testclient 'first rev'
16 """
18 second_p4changes = \
19 """Change 3 on 2006/04/13 by bob@testclient 'short desc truncated'
20 Change 2 on 2006/04/13 by slamb@testclient 'bar'
21 """
23 third_p4changes = \
24 """Change 5 on 2006/04/13 by mpatel@testclient 'first rev'
25 """
27 change_4_log = \
28 """Change 4 by mpatel@testclient on 2006/04/13 21:55:39
30 short desc truncated because this is a long description.
31 """
32 change_3_log = \
33 """Change 3 by bob@testclient on 2006/04/13 21:51:39
35 short desc truncated because this is a long description.
36 """
38 change_2_log = \
39 """Change 2 by slamb@testclient on 2006/04/13 21:46:23
41 creation
42 """
44 p4change = {
45 '3': change_3_log +
46 """Affected files ...
48 ... //depot/myproject/branch_b/branch_b_file#1 add
49 ... //depot/myproject/branch_b/whatbranch#1 branch
50 ... //depot/myproject/branch_c/whatbranch#1 branch
51 """,
52 '2': change_2_log +
53 """Affected files ...
55 ... //depot/myproject/trunk/whatbranch#1 add
56 ... //depot/otherproject/trunk/something#1 add
57 """,
58 '5': change_4_log +
59 """Affected files ...
61 ... //depot/myproject/branch_b/branch_b_file#1 add
62 ... //depot/myproject/branch_b#75 edit
63 ... //depot/myproject/branch_c/branch_c_file#1 add
64 """,
68 class MockP4Source(P4Source):
69 """Test P4Source which doesn't actually invoke p4."""
70 invocation = 0
72 def __init__(self, p4changes, p4change, *args, **kwargs):
73 P4Source.__init__(self, *args, **kwargs)
74 self.p4changes = p4changes
75 self.p4change = p4change
77 def _get_changes(self):
78 assert self.working
79 result = self.p4changes[self.invocation]
80 self.invocation += 1
81 return defer.succeed(result)
83 def _get_describe(self, dummy, num):
84 assert self.working
85 return defer.succeed(self.p4change[num])
87 class TestP4Poller(unittest.TestCase):
88 def setUp(self):
89 self.changes = []
90 self.addChange = self.changes.append
92 def testCheck(self):
93 """successful checks"""
94 self.t = MockP4Source(p4changes=[first_p4changes, second_p4changes],
95 p4change=p4change,
96 p4port=None, p4user=None,
97 p4base='//depot/myproject/',
98 split_file=lambda x: x.split('/', 1))
99 self.t.parent = self
101 # The first time, it just learns the change to start at.
102 self.assert_(self.t.last_change is None)
103 self.assert_(not self.t.working)
104 return maybeWait(self.t.checkp4().addCallback(self._testCheck2))
106 def _testCheck2(self, res):
107 self.assertEquals(self.changes, [])
108 self.assertEquals(self.t.last_change, '1')
110 # Subsequent times, it returns Change objects for new changes.
111 return self.t.checkp4().addCallback(self._testCheck3)
113 def _testCheck3(self, res):
114 self.assertEquals(len(self.changes), 3)
115 self.assertEquals(self.t.last_change, '3')
116 self.assert_(not self.t.working)
118 # They're supposed to go oldest to newest, so this one must be first.
119 self.assertEquals(self.changes[0].asText(),
120 Change(who='slamb',
121 files=['whatbranch'],
122 comments=change_2_log,
123 revision='2',
124 when=time.mktime((2006, 4, 13, 21, 46, 23, 3, 103, -1)),
125 branch='trunk').asText())
127 # These two can happen in either order, since they're from the same
128 # Perforce change.
129 self.assertIn(
130 Change(who='bob',
131 files=['branch_b_file',
132 'whatbranch'],
133 comments=change_3_log,
134 revision='3',
135 when=time.mktime((2006, 4, 13, 21, 51, 39, 3, 103, -1)),
136 branch='branch_b').asText(),
137 [c.asText() for c in self.changes])
138 self.assertIn(
139 Change(who='bob',
140 files=['whatbranch'],
141 comments=change_3_log,
142 revision='3',
143 when=time.mktime((2006, 4, 13, 21, 51, 39, 3, 103, -1)),
144 branch='branch_c').asText(),
145 [c.asText() for c in self.changes])
147 def testFailedChanges(self):
148 """'p4 changes' failure is properly reported"""
149 self.t = MockP4Source(p4changes=['Perforce client error:\n...'],
150 p4change={},
151 p4port=None, p4user=None)
152 self.t.parent = self
153 d = self.t.checkp4()
154 d.addBoth(self._testFailedChanges2)
155 return maybeWait(d)
157 def _testFailedChanges2(self, f):
158 self.assert_(isinstance(f, failure.Failure))
159 self.assertIn('Perforce client error', str(f))
160 self.assert_(not self.t.working)
162 def testFailedDescribe(self):
163 """'p4 describe' failure is properly reported"""
164 c = dict(p4change)
165 c['3'] = 'Perforce client error:\n...'
166 self.t = MockP4Source(p4changes=[first_p4changes, second_p4changes],
167 p4change=c, p4port=None, p4user=None)
168 self.t.parent = self
169 d = self.t.checkp4()
170 d.addCallback(self._testFailedDescribe2)
171 return maybeWait(d)
173 def _testFailedDescribe2(self, res):
174 # first time finds nothing; check again.
175 return self.t.checkp4().addBoth(self._testFailedDescribe3)
177 def _testFailedDescribe3(self, f):
178 self.assert_(isinstance(f, failure.Failure))
179 self.assertIn('Perforce client error', str(f))
180 self.assert_(not self.t.working)
181 self.assertEquals(self.t.last_change, '2')
183 def testAlreadyWorking(self):
184 """don't launch a new poll while old is still going"""
185 self.t = P4Source()
186 self.t.working = True
187 self.assert_(self.t.last_change is None)
188 d = self.t.checkp4()
189 d.addCallback(self._testAlreadyWorking2)
191 def _testAlreadyWorking2(self, res):
192 self.assert_(self.t.last_change is None)
194 def testSplitFile(self):
195 """Make sure split file works on branch only changes"""
196 self.t = MockP4Source(p4changes=[third_p4changes],
197 p4change=p4change,
198 p4port=None, p4user=None,
199 p4base='//depot/myproject/',
200 split_file=get_simple_split)
201 self.t.parent = self
202 self.t.last_change = 50
203 d = self.t.checkp4()
204 d.addCallback(self._testSplitFile)
206 def _testSplitFile(self, res):
207 self.assertEquals(len(self.changes), 2)
208 self.assertEquals(self.t.last_change, '5')