blob: d4f90de8842841d74489872ac9b795bd0bdcbec2 [file] [log] [blame]
joychen3cb228e2013-06-12 19:13:131#!/usr/bin/python
2
3# Copyright (c) 2013 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 xbuddy.py."""
8
9import os
10import shutil
joychen921e1fb2013-06-28 18:12:2011import tempfile
joychen3cb228e2013-06-12 19:13:1312import time
13import unittest
14
15import mox
16
joychenf8f07e22013-07-13 00:45:5117import gsutil_util
joychen3cb228e2013-06-12 19:13:1318import xbuddy
19
20#pylint: disable=W0212
Simran Basi99e63c02014-05-20 17:39:5221
22GS_ALTERNATE_DIR = 'gs://chromeos-alternate-archive/'
23
24
joychen3cb228e2013-06-12 19:13:1325class xBuddyTest(mox.MoxTestBase):
26 """Regression tests for xbuddy."""
27 def setUp(self):
28 mox.MoxTestBase.setUp(self)
29
joychen921e1fb2013-06-28 18:12:2030 self.static_image_dir = tempfile.mkdtemp('xbuddy_unittest_static')
joychen3cb228e2013-06-12 19:13:1331
joychen921e1fb2013-06-28 18:12:2032 self.mock_xb = xbuddy.XBuddy(
joychen5260b9a2013-07-16 21:48:0133 True,
joychen921e1fb2013-06-28 18:12:2034 static_dir=self.static_image_dir
35 )
36 self.images_dir = tempfile.mkdtemp('xbuddy_unittest_images')
37 self.mock_xb.images_dir = self.images_dir
joychen3cb228e2013-06-12 19:13:1338
39 def tearDown(self):
40 """Removes testing files."""
41 shutil.rmtree(self.static_image_dir)
joychen921e1fb2013-06-28 18:12:2042 shutil.rmtree(self.images_dir)
joychen3cb228e2013-06-12 19:13:1343
44 def testParseBoolean(self):
45 """Check that some common True/False strings are handled."""
46 self.assertEqual(xbuddy.XBuddy.ParseBoolean(None), False)
47 self.assertEqual(xbuddy.XBuddy.ParseBoolean('false'), False)
48 self.assertEqual(xbuddy.XBuddy.ParseBoolean('bs'), False)
49 self.assertEqual(xbuddy.XBuddy.ParseBoolean('true'), True)
50 self.assertEqual(xbuddy.XBuddy.ParseBoolean('y'), True)
51
joychenf8f07e22013-07-13 00:45:5152 def testLookupOfficial(self):
53 """Basic test of _LookupOfficial. Checks that a given suffix is handled."""
54 self.mox.StubOutWithMock(gsutil_util, 'GSUtilRun')
55 gsutil_util.GSUtilRun(mox.IgnoreArg(),
56 mox.IgnoreArg()).AndReturn('v')
57 expected = 'b-s/v'
58 self.mox.ReplayAll()
Chris Sosaea734d92013-10-11 18:28:5859 self.assertEqual(self.mock_xb._LookupOfficial('b', '-s'), expected)
joychenf8f07e22013-07-13 00:45:5160 self.mox.VerifyAll()
61
62 def testLookupChannel(self):
63 """Basic test of _LookupChannel. Checks that a given suffix is handled."""
64 self.mox.StubOutWithMock(gsutil_util, 'GetLatestVersionFromGSDir')
65 mock_data1 = '4100.68.0'
joychen562699a2013-08-13 22:22:1466 gsutil_util.GetLatestVersionFromGSDir(
67 mox.IgnoreArg(), with_release=False).AndReturn(mock_data1)
joychenf8f07e22013-07-13 00:45:5168 mock_data2 = 'R28-4100.68.0'
69 gsutil_util.GetLatestVersionFromGSDir(mox.IgnoreArg()).AndReturn(mock_data2)
70 self.mox.ReplayAll()
71 expected = 'b-release/R28-4100.68.0'
Simran Basi99e63c02014-05-20 17:39:5272 self.assertEqual(self.mock_xb._LookupChannel('b'),
73 expected)
joychenf8f07e22013-07-13 00:45:5174 self.mox.VerifyAll()
75
Chris Sosaea734d92013-10-11 18:28:5876 def testResolveVersionToBuildId_Official(self):
77 """Check _ResolveVersionToBuildId recognizes aliases for official builds."""
joychenf8f07e22013-07-13 00:45:5178 board = 'b'
79
80 # aliases that should be redirected to LookupOfficial
Chris Sosaea734d92013-10-11 18:28:5881
joychenf8f07e22013-07-13 00:45:5182 self.mox.StubOutWithMock(self.mock_xb, '_LookupOfficial')
Simran Basi99e63c02014-05-20 17:39:5283 self.mock_xb._LookupOfficial(board, image_dir=None)
84 self.mock_xb._LookupOfficial(board,
85 image_dir=GS_ALTERNATE_DIR)
86 self.mock_xb._LookupOfficial(board, 'paladin', image_dir=None)
87 self.mock_xb._LookupOfficial(board, 'paladin',
88 image_dir=GS_ALTERNATE_DIR)
joychenf8f07e22013-07-13 00:45:5189
90 self.mox.ReplayAll()
91 version = 'latest-official'
Chris Sosaea734d92013-10-11 18:28:5892 self.mock_xb._ResolveVersionToBuildId(board, version)
Simran Basi99e63c02014-05-20 17:39:5293 self.mock_xb._ResolveVersionToBuildId(board, version,
94 image_dir=GS_ALTERNATE_DIR)
joychenf8f07e22013-07-13 00:45:5195 version = 'latest-official-paladin'
Chris Sosaea734d92013-10-11 18:28:5896 self.mock_xb._ResolveVersionToBuildId(board, version)
Simran Basi99e63c02014-05-20 17:39:5297 self.mock_xb._ResolveVersionToBuildId(board, version,
98 image_dir=GS_ALTERNATE_DIR)
joychenf8f07e22013-07-13 00:45:5199 self.mox.VerifyAll()
100
Chris Sosaea734d92013-10-11 18:28:58101 def testResolveVersionToBuildId_Channel(self):
102 """Check _ResolveVersionToBuildId recognizes aliases for channels."""
joychenf8f07e22013-07-13 00:45:51103 board = 'b'
104
105 # aliases that should be redirected to LookupChannel
106 self.mox.StubOutWithMock(self.mock_xb, '_LookupChannel')
Simran Basi99e63c02014-05-20 17:39:52107 self.mock_xb._LookupChannel(board, image_dir=None)
108 self.mock_xb._LookupChannel(board, image_dir=GS_ALTERNATE_DIR)
109 self.mock_xb._LookupChannel(board, 'dev', image_dir=None)
110 self.mock_xb._LookupChannel(board, 'dev', image_dir=GS_ALTERNATE_DIR)
joychenf8f07e22013-07-13 00:45:51111
112 self.mox.ReplayAll()
113 version = 'latest'
Chris Sosaea734d92013-10-11 18:28:58114 self.mock_xb._ResolveVersionToBuildId(board, version)
Simran Basi99e63c02014-05-20 17:39:52115 self.mock_xb._ResolveVersionToBuildId(board, version,
116 image_dir=GS_ALTERNATE_DIR)
joychenf8f07e22013-07-13 00:45:51117 version = 'latest-dev'
Chris Sosaea734d92013-10-11 18:28:58118 self.mock_xb._ResolveVersionToBuildId(board, version)
Simran Basi99e63c02014-05-20 17:39:52119 self.mock_xb._ResolveVersionToBuildId(board, version,
120 image_dir=GS_ALTERNATE_DIR)
joychenf8f07e22013-07-13 00:45:51121 self.mox.VerifyAll()
joychen3cb228e2013-06-12 19:13:13122
123 def testBasicInterpretPath(self):
124 """Basic checks for splitting a path"""
joychen121fc9b2013-08-02 21:30:30125 path = 'parrot/R27-2455.0.0/test'
joychen7df67f72013-07-18 21:21:12126 expected = ('test', 'parrot', 'R27-2455.0.0', True)
joychen121fc9b2013-08-02 21:30:30127 self.assertEqual(self.mock_xb._InterpretPath(path=path), expected)
joychen7df67f72013-07-18 21:21:12128
joychen121fc9b2013-08-02 21:30:30129 path = 'parrot/R27-2455.0.0/full_payload'
130 expected = ('full_payload', 'parrot', 'R27-2455.0.0', True)
131 self.assertEqual(self.mock_xb._InterpretPath(path=path), expected)
132
133 path = 'parrot/R27-2455.0.0'
Chris Sosa0eecf96e2014-02-03 22:14:39134 expected = ('ANY', 'parrot', 'R27-2455.0.0', True)
joychen121fc9b2013-08-02 21:30:30135 self.assertEqual(self.mock_xb._InterpretPath(path=path), expected)
136
137 path = 'remote/parrot/R27-2455.0.0'
138 expected = ('test', 'parrot', 'R27-2455.0.0', False)
139 self.assertEqual(self.mock_xb._InterpretPath(path=path), expected)
140
141 path = 'local/parrot/R27-2455.0.0'
Chris Sosa0eecf96e2014-02-03 22:14:39142 expected = ('ANY', 'parrot', 'R27-2455.0.0', True)
joychen121fc9b2013-08-02 21:30:30143 self.assertEqual(self.mock_xb._InterpretPath(path=path), expected)
144
145 path = ''
Chris Sosa0eecf96e2014-02-03 22:14:39146 expected = ('ANY', None, 'latest', True)
147 self.assertEqual(self.mock_xb._InterpretPath(path=path), expected)
joychen3cb228e2013-06-12 19:13:13148
joychen121fc9b2013-08-02 21:30:30149 path = 'local'
Chris Sosa0eecf96e2014-02-03 22:14:39150 expected = ('ANY', None, 'latest', True)
151 self.assertEqual(self.mock_xb._InterpretPath(path=path), expected)
joychen7df67f72013-07-18 21:21:12152
joychenc3944cb2013-08-19 17:42:07153 path = 'local/parrot/latest/ANY'
154 expected = ('ANY', 'parrot', 'latest', True)
155 self.assertEqual(self.mock_xb._InterpretPath(path=path), expected)
156
joychen7df67f72013-07-18 21:21:12157
joychen3cb228e2013-06-12 19:13:13158 def testTimestampsAndList(self):
159 """Creation and listing of builds according to their timestamps."""
160 # make 3 different timestamp files
joychen921e1fb2013-06-28 18:12:20161 b_id11 = 'b1/v1'
162 b_id12 = 'b1/v2'
163 b_id23 = 'b2/v3'
164 xbuddy.Timestamp.UpdateTimestamp(self.mock_xb._timestamp_folder, b_id11)
165 time.sleep(0.05)
166 xbuddy.Timestamp.UpdateTimestamp(self.mock_xb._timestamp_folder, b_id12)
167 time.sleep(0.05)
168 xbuddy.Timestamp.UpdateTimestamp(self.mock_xb._timestamp_folder, b_id23)
joychen3cb228e2013-06-12 19:13:13169
170 # reference second one again
joychen921e1fb2013-06-28 18:12:20171 time.sleep(0.05)
172 xbuddy.Timestamp.UpdateTimestamp(self.mock_xb._timestamp_folder, b_id12)
joychen3cb228e2013-06-12 19:13:13173
174 # check that list returns the same 3 things, in last referenced order
joychen921e1fb2013-06-28 18:12:20175 result = self.mock_xb._ListBuildTimes()
176 self.assertEqual(result[0][0], b_id12)
177 self.assertEqual(result[1][0], b_id23)
178 self.assertEqual(result[2][0], b_id11)
179
180 def testSyncRegistry(self):
181 # check that there are no builds initially
182 result = self.mock_xb._ListBuildTimes()
183 self.assertEqual(len(result), 0)
184
185 # set up the dummy build/images directory with images
186 boards = ['a', 'b']
187 versions = ['v1', 'v2']
188 for b in boards:
189 os.makedirs(os.path.join(self.mock_xb.images_dir, b))
190 for v in versions:
191 os.makedirs(os.path.join(self.mock_xb.images_dir, b, v))
192
193 # Sync and check that they've been added to xBuddy's registry
194 self.mock_xb._SyncRegistryWithBuildImages()
195 result = self.mock_xb._ListBuildTimes()
196 self.assertEqual(len(result), 4)
joychen3cb228e2013-06-12 19:13:13197
198 ############### Public Methods
199 def testXBuddyCaching(self):
200 """Caching & replacement of timestamp files."""
joychen121fc9b2013-08-02 21:30:30201 path_a = ('remote', 'a', 'R0', 'test')
202 path_b = ('remote', 'b', 'R0', 'test')
Chris Sosaea734d92013-10-11 18:28:58203 self.mox.StubOutWithMock(gsutil_util, 'GSUtilRun')
204 self.mox.StubOutWithMock(self.mock_xb, '_Download')
joychen3cb228e2013-06-12 19:13:13205 self.mox.StubOutWithMock(self.mock_xb, '_Download')
206 for _ in range(8):
Chris Sosa75490802013-10-01 00:21:45207 self.mock_xb._Download(mox.IsA(str), mox.In(mox.IsA(str)))
joychen3cb228e2013-06-12 19:13:13208
Chris Sosaea734d92013-10-11 18:28:58209 # All non-release urls are invalid so we can meet expectations.
210 gsutil_util.GSUtilRun(mox.Not(mox.StrContains('-release')),
211 None).MultipleTimes().AndRaise(
212 gsutil_util.GSUtilError('bad url'))
213 gsutil_util.GSUtilRun(mox.StrContains('-release'), None).MultipleTimes()
214
joychen3cb228e2013-06-12 19:13:13215 self.mox.ReplayAll()
216
217 # requires default capacity
218 self.assertEqual(self.mock_xb.Capacity(), '5')
219
220 # Get 6 different images: a,b,c,d,e,f
joychen921e1fb2013-06-28 18:12:20221 images = ['a', 'b', 'c', 'd', 'e', 'f']
222 for c in images:
joychen562699a2013-08-13 22:22:14223 self.mock_xb.Get(('remote', c, 'R0', 'test'))
joychen921e1fb2013-06-28 18:12:20224 time.sleep(0.05)
joychen3cb228e2013-06-12 19:13:13225
226 # check that b,c,d,e,f are still stored
joychen921e1fb2013-06-28 18:12:20227 result = self.mock_xb._ListBuildTimes()
joychen3cb228e2013-06-12 19:13:13228 self.assertEqual(len(result), 5)
joychen921e1fb2013-06-28 18:12:20229
230 # Flip the list to get reverse chronological order
231 images.reverse()
232 for i in range(5):
joychenf8f07e22013-07-13 00:45:51233 self.assertEqual(result[i][0], '%s-release/R0' % images[i])
joychen3cb228e2013-06-12 19:13:13234
235 # Get b,a
joychen562699a2013-08-13 22:22:14236 self.mock_xb.Get(path_b)
joychen921e1fb2013-06-28 18:12:20237 time.sleep(0.05)
joychen562699a2013-08-13 22:22:14238 self.mock_xb.Get(path_a)
joychen921e1fb2013-06-28 18:12:20239 time.sleep(0.05)
joychen3cb228e2013-06-12 19:13:13240
241 # check that d,e,f,b,a are still stored
joychen921e1fb2013-06-28 18:12:20242 result = self.mock_xb._ListBuildTimes()
joychen3cb228e2013-06-12 19:13:13243 self.assertEqual(len(result), 5)
joychen921e1fb2013-06-28 18:12:20244 images_expected = ['a', 'b', 'f', 'e', 'd']
245 for i in range(5):
joychenf8f07e22013-07-13 00:45:51246 self.assertEqual(result[i][0], '%s-release/R0' % images_expected[i])
joychen3cb228e2013-06-12 19:13:13247
248 self.mox.VerifyAll()
249
250
251if __name__ == '__main__':
252 unittest.main()