add max_builds= to BuildSlave, thanks to Dustin Mitchell. Closes #48.
[buildbot.git] / buildbot / test / test_bonsaipoller.py
blobb8ca8115f8c55bbfdee30882c9baa934341c4ac0
1 # -*- test-case-name: buildbot.test.test_bonsaipoller -*-
3 from twisted.trial import unittest
4 from buildbot.changes.bonsaipoller import FileNode, CiNode, BonsaiResult, \
5 BonsaiParser, BonsaiPoller, InvalidResultError, EmptyResult
7 from StringIO import StringIO
8 from copy import deepcopy
9 import re
11 log1 = "Add Bug 338541a"
12 who1 = "sar@gmail.com"
13 date1 = 1161908700
14 log2 = "bug 357427 add static ctor/dtor methods"
15 who2 = "aarrg@ooacm.org"
16 date2 = 1161910620
17 log3 = "Testing log #3 lbah blah"
18 who3 = "huoents@hueont.net"
19 date3 = 1889822728
20 rev1 = "1.8"
21 file1 = "mozilla/testing/mochitest/tests/index.html"
22 rev2 = "1.1"
23 file2 = "mozilla/testing/mochitest/tests/test_bug338541.xhtml"
24 rev3 = "1.1812"
25 file3 = "mozilla/xpcom/threads/nsAutoLock.cpp"
26 rev4 = "1.3"
27 file4 = "mozilla/xpcom/threads/nsAutoLock.h"
28 rev5 = "2.4"
29 file5 = "mozilla/xpcom/threads/test.cpp"
31 nodes = []
32 files = []
33 files.append(FileNode(rev1,file1))
34 nodes.append(CiNode(log1, who1, date1, files))
36 files = []
37 files.append(FileNode(rev2, file2))
38 files.append(FileNode(rev3, file3))
39 nodes.append(CiNode(log2, who2, date2, files))
41 nodes.append(CiNode(log3, who3, date3, []))
43 goodParsedResult = BonsaiResult(nodes)
45 goodUnparsedResult = """\
46 <?xml version="1.0"?>
47 <queryResults>
48 <ci who="%s" date="%d">
49 <log>%s</log>
50 <files>
51 <f rev="%s">%s</f>
52 </files>
53 </ci>
54 <ci who="%s" date="%d">
55 <log>%s</log>
56 <files>
57 <f rev="%s">%s</f>
58 <f rev="%s">%s</f>
59 </files>
60 </ci>
61 <ci who="%s" date="%d">
62 <log>%s</log>
63 <files>
64 </files>
65 </ci>
66 </queryResults>
67 """ % (who1, date1, log1, rev1, file1,
68 who2, date2, log2, rev2, file2, rev3, file3,
69 who3, date3, log3)
71 badUnparsedResult = deepcopy(goodUnparsedResult)
72 badUnparsedResult = badUnparsedResult.replace("</queryResults>", "")
74 invalidDateResult = deepcopy(goodUnparsedResult)
75 invalidDateResult = invalidDateResult.replace(str(date1), "foobar")
77 missingRevisionResult = deepcopy(goodUnparsedResult)
78 missingRevisionResult = missingRevisionResult.replace("rev=\""+rev3+"\"", "")
80 missingFilenameResult = deepcopy(goodUnparsedResult)
81 missingFilenameResult = missingFilenameResult.replace(file2, "")
83 duplicateLogResult = deepcopy(goodUnparsedResult)
84 duplicateLogResult = re.sub("<log>"+log1+"</log>",
85 "<log>blah</log><log>blah</log>",
86 duplicateLogResult)
88 duplicateFilesResult = deepcopy(goodUnparsedResult)
89 duplicateFilesResult = re.sub("<files>\s*</files>",
90 "<files></files><files></files>",
91 duplicateFilesResult)
93 missingCiResult = deepcopy(goodUnparsedResult)
94 r = re.compile("<ci.*</ci>", re.DOTALL | re.MULTILINE)
95 missingCiResult = re.sub(r, "", missingCiResult)
97 badResultMsgs = { 'badUnparsedResult':
98 "BonsaiParser did not raise an exception when given a bad query",
99 'invalidDateResult':
100 "BonsaiParser did not raise an exception when given an invalid date",
101 'missingRevisionResult':
102 "BonsaiParser did not raise an exception when a revision was missing",
103 'missingFilenameResult':
104 "BonsaiParser did not raise an exception when a filename was missing",
105 'duplicateLogResult':
106 "BonsaiParser did not raise an exception when there was two <log> tags",
107 'duplicateFilesResult':
108 "BonsaiParser did not raise an exception when there was two <files> tags",
109 'missingCiResult':
110 "BonsaiParser did not raise an exception when there was no <ci> tags"
113 class FakeBonsaiPoller(BonsaiPoller):
114 def __init__(self):
115 BonsaiPoller.__init__(self, "fake url", "fake module", "fake branch")
117 class TestBonsaiPoller(unittest.TestCase):
118 def testFullyFormedResult(self):
119 br = BonsaiParser(StringIO(goodUnparsedResult))
120 result = br.getData()
121 # make sure the result is a BonsaiResult
122 self.failUnless(isinstance(result, BonsaiResult))
123 # test for successful parsing
124 self.failUnlessEqual(goodParsedResult, result,
125 "BonsaiParser did not return the expected BonsaiResult")
127 def testBadUnparsedResult(self):
128 try:
129 BonsaiParser(StringIO(badUnparsedResult))
130 self.fail(badResultMsgs["badUnparsedResult"])
131 except InvalidResultError:
132 pass
134 def testInvalidDateResult(self):
135 try:
136 BonsaiParser(StringIO(invalidDateResult))
137 self.fail(badResultMsgs["invalidDateResult"])
138 except InvalidResultError:
139 pass
141 def testMissingRevisionResult(self):
142 try:
143 BonsaiParser(StringIO(missingRevisionResult))
144 self.fail(badResultMsgs["missingRevisionResult"])
145 except InvalidResultError:
146 pass
148 def testMissingFilenameResult(self):
149 try:
150 BonsaiParser(StringIO(missingFilenameResult))
151 self.fail(badResultMsgs["missingFilenameResult"])
152 except InvalidResultError:
153 pass
155 def testDuplicateLogResult(self):
156 try:
157 BonsaiParser(StringIO(duplicateLogResult))
158 self.fail(badResultMsgs["duplicateLogResult"])
159 except InvalidResultError:
160 pass
162 def testDuplicateFilesResult(self):
163 try:
164 BonsaiParser(StringIO(duplicateFilesResult))
165 self.fail(badResultMsgs["duplicateFilesResult"])
166 except InvalidResultError:
167 pass
169 def testMissingCiResult(self):
170 try:
171 BonsaiParser(StringIO(missingCiResult))
172 self.fail(badResultMsgs["missingCiResult"])
173 except EmptyResult:
174 pass
176 def testChangeNotSubmitted(self):
177 "Make sure a change is not submitted if the BonsaiParser fails"
178 poller = FakeBonsaiPoller()
179 lastChangeBefore = poller.lastChange
180 poller._process_changes(StringIO(badUnparsedResult))
181 # self.lastChange will not be updated if the change was not submitted
182 self.failUnlessEqual(lastChangeBefore, poller.lastChange)