66e4f06c97a8fdbfedfc4b7c72217d41250409ac
[build-farm.git] / buildfarm / tests / test_data.py
1 #!/usr/bin/python
2 # Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2010
3 #
4 #   This program is free software; you can redistribute it and/or modify
5 #   it under the terms of the GNU General Public License as published by
6 #   the Free Software Foundation; either version 3 of the License, or
7 #   (at your option) any later version.
8 #
9 #   This program is distributed in the hope that it will be useful,
10 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 #   GNU General Public License for more details.
13 #
14 #   You should have received a copy of the GNU General Public License
15 #   along with this program; if not, write to the Free Software
16 #   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 from cStringIO import StringIO
19 import os
20 import tempfile
21 import testtools
22 import time
23 import unittest
24
25 from buildfarm import data
26
27 from buildfarm.tests import BuildFarmTestCase
28
29
30 class NonexistantTests(unittest.TestCase):
31
32     def test_nonexistant(self):
33         self.assertRaises(
34             Exception, data.BuildResultStore, "somedirthatdoesn'texist", None)
35
36
37 class ReadTreesFromConfTests(testtools.TestCase):
38
39     def create_file(self, contents):
40         (fd, path) = tempfile.mkstemp()
41         f = os.fdopen(fd, 'w')
42         self.addCleanup(os.remove, path)
43         try:
44             f.write(contents)
45         finally:
46             f.close()
47         return path
48
49     def test_read_trees_from_conf_ko(self):
50         name = self.create_file("""
51 [foo]
52 param1 = fooval1
53 param2 = fooval2
54 param3 = fooval3
55
56 [bar]
57 param1 = barval1
58 param2 = barval2
59 param3 = barval3
60 """)
61         self.assertRaises(
62             Exception, data.read_trees_from_conf, name, None)
63
64     def test_read_trees_from_conf(self):
65         name = self.create_file("""
66 [pidl]
67 scm = git
68 repo = samba.git
69 branch = master
70 subdir = pidl/
71
72 [rsync]
73 scm = git
74 repo = rsync.git
75 branch = HEAD
76 """)
77         t = data.read_trees_from_conf(name)
78         self.assertEquals(
79             t["pidl"].scm,
80             "git")
81
82
83 class BuildResultStoreTests(BuildFarmTestCase):
84
85     def setUp(self):
86         super(BuildResultStoreTests, self).setUp()
87
88         self.write_compilers(["cc"])
89         self.write_trees({"tdb": {"scm": "git", "repo": "tdb", "branch": "master"}})
90
91         self.x = data.BuildResultStore(self.path)
92
93     def test_build_fname(self):
94         self.assertEquals(
95             self.x.build_fname("mytree", "myhost", "cc"),
96             "%s/data/upload/build.mytree.myhost.cc" % self.path)
97         self.assertEquals(
98             self.x.build_fname("mytree", "myhost", "cc", 123),
99             "%s/data/oldrevs/build.mytree.myhost.cc-123" % self.path)
100
101     def test_cache_fname(self):
102         self.assertEquals(
103             self.x.cache_fname("mytree", "myhost", "cc", 123),
104             "%s/cache/build.mytree.myhost.cc-123" % self.path)
105         self.assertEquals(
106             self.x.cache_fname("mytree", "myhost", "cc"),
107             "%s/cache/build.mytree.myhost.cc" % self.path)
108
109     def test_build_age_mtime(self):
110         path = self.create_mock_logfile("tdb", "charis", "cc")
111         # Set mtime to something in the past
112         os.utime(path, (time.time(), time.time() - 990))
113         build = self.x.get_build("tdb", "charis", "cc")
114         age = build.age_mtime()
115         self.assertTrue(age >= 990 and age <= 1000, "age was %d" % age)
116
117     def test_get_build_nonexistant(self):
118         self.assertRaises(data.NoSuchBuildError, self.x.get_build, "tdb",
119             "charis", "cc")
120
121     def test_build_age_ctime(self):
122         path = self.create_mock_logfile("tdb", "charis", "cc")
123         # Set mtime to something in the past
124         build = self.x.get_build("tdb", "charis", "cc")
125         age = build.age_ctime()
126         self.assertTrue(age >= 0 and age <= 10, "age was %d" % age)
127
128     def test_read_log(self):
129         path = self.create_mock_logfile("tdb", "charis", "cc",
130             contents="This is what a log file looks like.")
131         build = self.x.get_build("tdb", "charis", "cc")
132         self.assertEquals("This is what a log file looks like.", build.read_log().read())
133
134     def test_read_err(self):
135         self.create_mock_logfile("tdb", "charis", "cc")
136         path = self.create_mock_logfile("tdb", "charis", "cc",
137             kind="stderr",
138             contents="This is what an stderr file looks like.")
139         build = self.x.get_build("tdb", "charis", "cc")
140         self.assertEquals("This is what an stderr file looks like.", build.read_err().read())
141
142     def test_read_err_nofile(self):
143         self.create_mock_logfile("tdb", "charis", "cc")
144         build = self.x.get_build("tdb", "charis", "cc")
145         self.assertEquals("", build.read_err().read())
146
147     def test_revision_details(self):
148         self.create_mock_logfile("tdb", "charis", "cc", contents="""
149 BUILD COMMIT REVISION: 43
150 bla
151 BUILD REVISION: 42
152 BUILD COMMIT TIME: 3 August 2010
153 """)
154         build = self.x.get_build("tdb", "charis", "cc")
155         self.assertEquals(("42", "43", "3 August 2010"), build.revision_details())
156
157     def test_revision_details_no_timestamp(self):
158         self.create_mock_logfile("tdb", "charis", "cc", contents="""
159 BUILD COMMIT REVISION: 43
160 BUILD REVISION: 42
161 BLA
162 """)
163         build = self.x.get_build("tdb", "charis", "cc")
164         self.assertEquals(("42", "43", None), build.revision_details())
165
166     def test_err_count(self):
167         self.create_mock_logfile("tdb", "charis", "cc")
168         self.create_mock_logfile("tdb", "charis", "cc", kind="stderr", contents="""error1
169 error2
170 error3""")
171         build = self.x.get_build("tdb", "charis", "cc")
172         self.assertEquals(3, build.err_count())
173
174     def test_has_host(self):
175         self.assertFalse(self.x.has_host("charis"))
176         self.create_mock_logfile("tdb", "charis", "cc")
177         self.assertTrue(self.x.has_host("charis"))
178
179
180 class BuildStatusFromLogs(testtools.TestCase):
181
182     def parse_logs(self, log, err):
183         return data.build_status_from_logs(StringIO(log), StringIO(err))
184
185     def test_nothing(self):
186         s = self.parse_logs("", "")
187         self.assertEquals([], s.stages)
188         self.assertEquals(set(), s.other_failures)
189
190     def test_disk_full(self):
191         self.assertEquals(set(["disk full"]),
192             self.parse_logs("foo\nbar\nNo space left on device\nla\n",
193                 "").other_failures)
194         self.assertEquals(set(["disk full"]),
195             self.parse_logs(
196                 "", "foo\nbar\nNo space left on device\nla\n").other_failures)
197
198     def test_timeout(self):
199         self.assertEquals(set(["timeout"]),
200             self.parse_logs("foo\nbar\nmaximum runtime exceeded\nla\n",
201                 "").other_failures)
202
203     def test_failed_test(self):
204         log = """
205 TEST STATUS:1
206 """
207         res = self.parse_logs(log, "")
208         self.assertEquals(res.stages, [
209             ("TEST", 1)])
210
211     def test_failed_test_whitespace(self):
212         log = """
213 TEST STATUS:  1
214 """
215         res = self.parse_logs(log, "")
216         self.assertEquals(res.stages,
217             [("TEST", 1)])
218
219     def test_failed_test_noise(self):
220         log = """
221 CONFIGURE STATUS: 2
222 TEST STATUS:  1
223 CC_CHECKER STATUS:      2
224 """
225         res = self.parse_logs(log, "")
226         self.assertEquals(res.stages,
227             [("CONFIGURE", 2), ("TEST", 1), ("CC_CHECKER", 2)])
228
229     def test_no_test_output(self):
230         log = """
231 CONFIGURE STATUS: 2
232 TEST STATUS: 0
233 CC_CHECKER STATUS:      2
234 """
235         res = self.parse_logs(log, "")
236         self.assertEquals(res.stages,
237             [("CONFIGURE", 2), ("TEST", 0), ("CC_CHECKER", 2)])
238
239     def test_granular_test(self):
240         log = """
241 CONFIGURE STATUS: 2
242 testsuite-success: toto
243 testsuite-failure: foo
244 testsuite-failure: bar
245 testsuite-failure: biz
246 TEST STATUS: 1
247 CC_CHECKER STATUS:      2
248 """
249         res = self.parse_logs(log, "")
250         self.assertEquals(res.stages,
251             [("CONFIGURE", 2), ("TEST", 3), ("CC_CHECKER", 2)])
252