blob: dd090821ce02e22417db2c88a4013485c716539f [file] [log] [blame]
Frank Farzan37761d12011-12-01 14:29:08 -08001#!/usr/bin/python
2#
3# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""Unit tests for devserver_util module."""
8
9import os
10import shutil
11import tempfile
12import unittest
13
14import devserver_util
15
16
17# Fake Dev Server Layout:
18TEST_LAYOUT = {
19 'test-board-1': ['R17-1413.0.0-a1-b1346', 'R17-18.0.0-a1-b1346'],
20 'test-board-2': ['R16-2241.0.0-a0-b2', 'R17-2.0.0-a1-b1346']
21}
22
23
24class DevServerUtilTest(unittest.TestCase):
25
26 def setUp(self):
27 self._static_dir = tempfile.mkdtemp()
28 self._outside_sandbox_dir = tempfile.mkdtemp()
29
30 for board, builds in TEST_LAYOUT.iteritems():
31 board_path = os.path.join(self._static_dir, board)
32 os.mkdir(board_path)
33 for build in builds:
34 build_path = os.path.join(board_path, build)
35 os.mkdir(build_path)
36 with open(os.path.join(build_path,
37 devserver_util.TEST_IMAGE), 'w') as f:
38 f.write('TEST_IMAGE')
39 with open(os.path.join(build_path,
40 devserver_util.STATEFUL_UPDATE), 'w') as f:
41 f.write('STATEFUL_UPDATE')
42 with open(os.path.join(build_path,
43 devserver_util.ROOT_UPDATE), 'w') as f:
44 f.write('ROOT_UPDATE')
45 # AU payloads.
46 au_dir = os.path.join(build_path, devserver_util.AU_BASE)
47 nton_dir = os.path.join(au_dir, build + devserver_util.NTON_DIR_SUFFIX)
48 os.makedirs(nton_dir)
49 with open(os.path.join(nton_dir,
50 devserver_util.ROOT_UPDATE), 'w') as f:
51 f.write('ROOT_UPDATE')
52 mton_dir = os.path.join(au_dir, build + devserver_util.MTON_DIR_SUFFIX)
53 os.makedirs(mton_dir)
54 with open(os.path.join(mton_dir,
55 devserver_util.ROOT_UPDATE), 'w') as f:
56 f.write('ROOT_UPDATE')
57
58 def tearDown(self):
59 shutil.rmtree(self._static_dir)
60 shutil.rmtree(self._outside_sandbox_dir)
61
62 def testParsePayloadList(self):
63 archive_url_prefix = ('gs://chromeos-image-archive/x86-mario-release/'
64 'R17-1413.0.0-a1-b1346/')
65 mton_url = (archive_url_prefix + 'chromeos_R17-1412.0.0-a1-b1345_'
66 'R17-1413.0.0-a1_x86-mario_delta_dev.bin')
67 nton_url = (archive_url_prefix + 'chromeos_R17-1413.0.0-a1_'
68 'R17-1413.0.0-a1_x86-mario_delta_dev.bin')
69 full_url = (archive_url_prefix + 'chromeos_R17-1413.0.0-a1_'
70 'x86-mario_full_dev.bin')
71 full_url_out, nton_url_out, mton_url_out = (
72 devserver_util.ParsePayloadList([full_url, nton_url, mton_url]))
73 self.assertEqual([full_url, nton_url, mton_url],
74 [full_url_out, nton_url_out, mton_url_out])
75
76 archive_url_prefix = ('gs://chromeos-image-archive/x86-alex_he-release/'
77 'R18-1420.0.0-a1-b541')
78 mton_url = (archive_url_prefix + 'chromeos_R18-1418.0.0-a1-b540_'
79 'R18-1420.0.0-a1_x86-alex_he_delta_dev.bin')
80 nton_url = (archive_url_prefix + 'chromeos_R18-1420.0.0-a1_'
81 'R18-1420.0.0-a1_x86-alex_he_delta_dev.bin')
82 full_url = (archive_url_prefix + 'chromeos_R18-1420.0.0-a1_'
83 'x86-alex_he_full_dev.bin')
84 full_url_out, nton_url_out, mton_url_out = (
85 devserver_util.ParsePayloadList([full_url, nton_url, mton_url]))
86 self.assertEqual([full_url, nton_url, mton_url],
87 [full_url_out, nton_url_out, mton_url_out])
88
89 def testDownloadBuildFromGS(self):
90 self.fail('Not implemented.')
91
92 def testInstallBuild(self):
93 self.fail('Not implemented.')
94
95 def testPrepareAutotestPkgs(self):
96 self.fail('Not implemented.')
97
98 def testSafeSandboxAccess(self):
99 # Path is in sandbox.
100 self.assertTrue(
101 devserver_util.SafeSandboxAccess(
102 self._static_dir, os.path.join(self._static_dir, 'some-board')))
103
104 # Path is sandbox.
105 self.assertFalse(
106 devserver_util.SafeSandboxAccess(self._static_dir, self._static_dir))
107
108 # Path is outside the sandbox.
109 self.assertFalse(
110 devserver_util.SafeSandboxAccess(self._static_dir,
111 self._outside_sandbox_dir))
112
113 # Path contains '..'.
114 self.assertFalse(
115 devserver_util.SafeSandboxAccess(
116 self._static_dir, os.path.join(self._static_dir, os.pardir)))
117
118 # Path contains symbolic link references.
119 os.chdir(self._static_dir)
120 os.symlink(os.pardir, 'parent')
121 self.assertFalse(
122 devserver_util.SafeSandboxAccess(
123 self._static_dir, os.path.join(self._static_dir, os.pardir)))
124
125 def testAcquireReleaseLocks(self):
126 # Successful lock and unlock.
127 lock_file = devserver_util.AcquireLock(self._static_dir, 'test-lock')
128 self.assertTrue(os.path.exists(lock_file))
129 devserver_util.ReleaseLock(self._static_dir, 'test-lock')
130 self.assertFalse(os.path.exists(lock_file))
131
132 # Attempt to lock an existing directory.
133 devserver_util.AcquireLock(self._static_dir, 'test-lock')
134 self.assertRaises(devserver_util.DevServerUtilError,
135 devserver_util.AcquireLock, self._static_dir, 'test-lock')
136
137 def testFindMatchingBoards(self):
138 for key in TEST_LAYOUT:
139 # Partial match with multiple boards.
140 self.assertEqual(
141 set(devserver_util.FindMatchingBoards(self._static_dir, key[:-5])),
142 set(TEST_LAYOUT.keys()))
143
144 # Absolute match.
145 self.assertEqual(
146 devserver_util.FindMatchingBoards(self._static_dir, key), [key])
147
148 # Invalid partial match.
149 self.assertEqual(
150 devserver_util.FindMatchingBoards(self._static_dir, 'asdfsadf'), [])
151
152 def testFindMatchingBuilds(self):
153 # Try a partial board and build match with single match.
154 self.assertEqual(
155 devserver_util.FindMatchingBuilds(self._static_dir, 'test-board',
156 'R17-1413'),
157 [('test-board-1', 'R17-1413.0.0-a1-b1346')])
158
159 # Try a partial board and build match with multiple match.
160 actual = set(devserver_util.FindMatchingBuilds(
161 self._static_dir, 'test-board', 'R17'))
162 expected = set([('test-board-1', 'R17-1413.0.0-a1-b1346'),
163 ('test-board-1', 'R17-18.0.0-a1-b1346'),
164 ('test-board-2', 'R17-2.0.0-a1-b1346')])
165 self.assertEqual(actual, expected)
166
167 def testGetLatestBuildVersion(self):
168 self.assertEqual(
169 devserver_util.GetLatestBuildVersion(self._static_dir, 'test-board-1'),
170 'R17-1413.0.0-a1-b1346')
171
172 def testFindBuild(self):
173 # Ensure no matching boards raises exception for latest.
174 self.assertRaises(
175 devserver_util.DevServerUtilError, devserver_util.FindBuild,
176 self._static_dir, 'aasdf', 'latest')
177
178 # Ensure no matching builds or boards raises an exception.
179 self.assertRaises(
180 devserver_util.DevServerUtilError, devserver_util.FindBuild,
181 self._static_dir, 'aasdf', 'asdgsadg')
182
183 # Ensure latest returns the proper build.
184 self.assertEqual(
185 devserver_util.FindBuild(self._static_dir, 'test-board-1', 'latest'),
186 ('test-board-1', 'R17-1413.0.0-a1-b1346'))
187
188 # Ensure specific board, build is returned.
189 self.assertEqual(
190 devserver_util.FindBuild(self._static_dir, 'test-board-1',
191 'R17-18.0.0-a1-b1346'),
192 ('test-board-1', 'R17-18.0.0-a1-b1346'))
193
194 # Ensure too many matches raises an exception.
195 self.assertRaises(
196 devserver_util.DevServerUtilError, devserver_util.FindBuild,
197 self._static_dir, 'test-board', 'R17')
198
199 def testCloneBuild(self):
200 test_prefix = 'abc'
201 test_tag = test_prefix + '/123'
202 abc_path = os.path.join(self._static_dir, devserver_util.DEV_BUILD_PREFIX,
203 test_tag)
204
205 os.mkdir(os.path.join(self._static_dir, test_prefix))
206
207 # Verify leaf path is created and proper values returned.
208 board, builds = TEST_LAYOUT.items()[0]
209 dev_build = devserver_util.CloneBuild(self._static_dir, board, builds[0],
210 test_tag)
211 self.assertEquals(dev_build, abc_path)
212 self.assertTrue(os.path.exists(abc_path))
213 self.assertTrue(os.path.isfile(os.path.join(
214 abc_path, devserver_util.TEST_IMAGE)))
215 self.assertTrue(os.path.isfile(os.path.join(
216 abc_path, devserver_util.ROOT_UPDATE)))
217 self.assertTrue(os.path.isfile(os.path.join(
218 abc_path, devserver_util.STATEFUL_UPDATE)))
219
220 # Verify force properly removes the old directory.
221 junk_path = os.path.join(dev_build, 'junk')
222 with open(junk_path, 'w') as f:
223 f.write('hello!')
224 remote_dir = devserver_util.CloneBuild(
225 self._static_dir, board, builds[0], test_tag, force=True)
226 self.assertEquals(remote_dir, abc_path)
227 self.assertTrue(os.path.exists(abc_path))
228 self.assertTrue(os.path.isfile(os.path.join(
229 abc_path, devserver_util.TEST_IMAGE)))
230 self.assertTrue(os.path.isfile(os.path.join(
231 abc_path, devserver_util.ROOT_UPDATE)))
232 self.assertTrue(os.path.isfile(os.path.join(
233 abc_path, devserver_util.STATEFUL_UPDATE)))
234 self.assertFalse(os.path.exists(junk_path))
235
236 def testGetControlFile(self):
237 control_file_dir = os.path.join(
238 self._static_dir, 'test-board-1', 'R17-1413.0.0-a1-b1346', 'server',
239 'site_tests', 'network_VPN')
240 os.makedirs(control_file_dir)
241 with open(os.path.join(control_file_dir, 'control'), 'w') as f:
242 f.write('hello!')
243
244 control_content = devserver_util.GetControlFile(
245 self._static_dir, 'test-board-1', 'R17-1413.0.0-a1-b1346',
246 os.path.join('server', 'site_tests', 'network_VPN', 'control'))
247 self.assertEqual(control_content, 'hello!')
248
249 def testListAutoupdateTargets(self):
250 for board, builds in TEST_LAYOUT.iteritems():
251 for build in builds:
252 au_targets = devserver_util.ListAutoupdateTargets(self._static_dir,
253 board, build)
254 self.assertEqual(set(au_targets),
255 set([build + devserver_util.NTON_DIR_SUFFIX,
256 build + devserver_util.MTON_DIR_SUFFIX]))
257
258
259if __name__ == '__main__':
260 unittest.main()