blob: ad4a82ec95f05c811a01e77fb0aa50bbbb7b18e7 [file] [log] [blame]
Mike Frysingere58c0e22017-10-04 15:43:30 -04001# -*- coding: utf-8 -*-
Benjamin Gordon2d7bf582017-07-12 10:11:26 -06002# Copyright 2017 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Tests for cros_sdk."""
7
8from __future__ import print_function
9
10import os
Mike Frysingeredc04912019-11-16 01:30:43 -050011import unittest
Benjamin Gordon2d7bf582017-07-12 10:11:26 -060012
13from chromite.lib import cros_build_lib
14from chromite.lib import cros_logging as logging
Benjamin Gordon74645232018-05-04 17:40:42 -060015from chromite.lib import cros_sdk_lib
Benjamin Gordon2d7bf582017-07-12 10:11:26 -060016from chromite.lib import cros_test_lib
17from chromite.lib import osutils
18from chromite.lib import sudo
19
20
Mike Frysingeredc04912019-11-16 01:30:43 -050021# This long decorator triggers a false positive in the docstring test.
22# https://github.com/PyCQA/pylint/issues/3077
23# pylint: disable=bad-docstring-quotes
24@unittest.skipIf(cros_build_lib.IsInsideChroot(),
25 'Tests only make sense outside the chroot')
Benjamin Gordon03c56e42017-09-11 15:48:39 -040026class CrosSdkPrerequisitesTest(cros_test_lib.TempDirTestCase):
27 """Tests for required packages on the host machine.
28
29 These are not real unit tests. If these tests fail, it means your machine is
30 missing necessary commands to support image-backed chroots. Run cros_sdk in
31 a terminal to get info about what you need to install.
32 """
33
34 def testLvmCommandsPresent(self):
35 """Check for commands from the lvm2 package."""
36 with sudo.SudoKeepAlive():
37 cmd = ['lvs', '--version']
Mike Frysinger45602c72019-09-22 02:15:11 -040038 result = cros_build_lib.run(cmd, error_code_ok=True)
Benjamin Gordon03c56e42017-09-11 15:48:39 -040039 self.assertEqual(result.returncode, 0)
40
41 def testThinProvisioningToolsPresent(self):
42 """Check for commands from the thin-provisioning-tools package."""
43 with sudo.SudoKeepAlive():
44 cmd = ['thin_check', '-V']
Mike Frysinger45602c72019-09-22 02:15:11 -040045 result = cros_build_lib.run(cmd, error_code_ok=True)
Benjamin Gordon03c56e42017-09-11 15:48:39 -040046 self.assertEqual(result.returncode, 0)
47
48 def testLosetupCommandPresent(self):
49 """Check for commands from the mount package."""
50 with sudo.SudoKeepAlive():
51 cmd = ['losetup', '--help']
Mike Frysinger45602c72019-09-22 02:15:11 -040052 result = cros_build_lib.run(cmd, error_code_ok=True)
Benjamin Gordon03c56e42017-09-11 15:48:39 -040053 self.assertEqual(result.returncode, 0)
54
55
Mike Frysingeredc04912019-11-16 01:30:43 -050056@unittest.skipIf(cros_build_lib.IsInsideChroot(),
57 'Tests only make sense outside the chroot')
58@unittest.skip(
59 'These are triggering hangs inside lvm when run through run_tests. '
60 'https://crbug.com/764335')
Benjamin Gordon2d7bf582017-07-12 10:11:26 -060061class CrosSdkSnapshotTest(cros_test_lib.TempDirTestCase):
62 """Tests for the snapshot functionality in cros_sdk."""
63
64 def setUp(self):
65 with sudo.SudoKeepAlive():
66 # Create just enough of a chroot to fool cros_sdk into accepting it.
67 self.chroot = os.path.join(self.tempdir, 'chroot')
Benjamin Gordon74645232018-05-04 17:40:42 -060068 cros_sdk_lib.MountChroot(self.chroot, create=True)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -060069 logging.debug('Chroot mounted on %s', self.chroot)
70
71 chroot_etc = os.path.join(self.chroot, 'etc')
72 osutils.SafeMakedirsNonRoot(chroot_etc)
73
74 self.chroot_version_file = os.path.join(chroot_etc, 'cros_chroot_version')
75 osutils.Touch(self.chroot_version_file, makedirs=True)
76
77 def tearDown(self):
78 with sudo.SudoKeepAlive():
Don Garrett36650112018-06-28 15:54:34 -070079 cros_sdk_lib.CleanupChrootMount(self.chroot, delete=True)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -060080
81 def _crosSdk(self, args):
82 cmd = ['cros_sdk', '--chroot', self.chroot]
83 cmd.extend(args)
84
85 try:
Mike Frysinger45602c72019-09-22 02:15:11 -040086 result = cros_build_lib.run(
Benjamin Gordon2d7bf582017-07-12 10:11:26 -060087 cmd, print_cmd=False, capture_output=True, error_code_ok=True,
88 combine_stdout_stderr=True)
89 except cros_build_lib.RunCommandError as e:
90 raise SystemExit('Running %r failed!: %s' % (cmd, e))
91
92 return result.returncode, result.output
93
94 def testSnapshotsRequireImage(self):
95 code, output = self._crosSdk(['--snapshot-list', '--nouse-image'])
96 self.assertNotEqual(code, 0)
97 self.assertIn('Snapshot operations are not compatible with', output)
98
99 code, output = self._crosSdk(['--snapshot-delete', 'test', '--nouse-image'])
100 self.assertNotEqual(code, 0)
101 self.assertIn('Snapshot operations are not compatible with', output)
102
103 code, output = self._crosSdk(['--snapshot-create', 'test', '--nouse-image'])
104 self.assertNotEqual(code, 0)
105 self.assertIn('Snapshot operations are not compatible with', output)
106
107 code, output = self._crosSdk(['--snapshot-restore', 'test',
108 '--nouse-image'])
109 self.assertNotEqual(code, 0)
110 self.assertIn('Snapshot operations are not compatible with', output)
111
112 def testSnapshotWithDeleteChroot(self):
113 code, output = self._crosSdk(['--delete', '--snapshot-list'])
114 self.assertNotEqual(code, 0)
115 self.assertIn('Trying to enter or snapshot the chroot', output)
116
117 code, output = self._crosSdk(['--delete', '--snapshot-delete', 'test'])
118 self.assertNotEqual(code, 0)
119 self.assertIn('Trying to enter or snapshot the chroot', output)
120
121 code, output = self._crosSdk(['--delete', '--snapshot-create', 'test'])
122 self.assertNotEqual(code, 0)
123 self.assertIn('Trying to enter or snapshot the chroot', output)
124
125 code, output = self._crosSdk(['--delete', '--snapshot-restore', 'test'])
126 self.assertNotEqual(code, 0)
127 self.assertIn('Trying to enter or snapshot the chroot', output)
128
129 def testEmptySnapshotList(self):
130 code, output = self._crosSdk(['--snapshot-list'])
131 self.assertEqual(code, 0)
132 self.assertEqual(output, '')
133
134 def testOneSnapshot(self):
135 code, _ = self._crosSdk(['--snapshot-create', 'test'])
136 self.assertEqual(code, 0)
137
138 code, output = self._crosSdk(['--snapshot-list'])
139 self.assertEqual(code, 0)
140 self.assertEqual(output.strip(), 'test')
141
142 def testMultipleSnapshots(self):
143 code, _ = self._crosSdk(['--snapshot-create', 'test'])
144 self.assertEqual(code, 0)
145 code, _ = self._crosSdk(['--snapshot-create', 'test2'])
146 self.assertEqual(code, 0)
147
148 code, output = self._crosSdk(['--snapshot-list'])
149 self.assertEqual(code, 0)
150 self.assertSetEqual(set(output.strip().split('\n')), {'test', 'test2'})
151
152 def testCantCreateSameSnapshotTwice(self):
153 code, _ = self._crosSdk(['--snapshot-create', 'test'])
154 self.assertEqual(code, 0)
155 code, _ = self._crosSdk(['--snapshot-create', 'test'])
156 self.assertNotEqual(code, 0)
157
158 code, output = self._crosSdk(['--snapshot-list'])
159 self.assertEqual(code, 0)
160 self.assertEqual(output.strip(), 'test')
161
162 def testCreateSnapshotMountsAsNeeded(self):
163 with sudo.SudoKeepAlive():
Benjamin Gordon74645232018-05-04 17:40:42 -0600164 cros_sdk_lib.CleanupChrootMount(self.chroot)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -0600165
166 code, _ = self._crosSdk(['--snapshot-create', 'test'])
167 self.assertEqual(code, 0)
Mike Frysingerf2fa7d62017-12-14 18:33:59 -0500168 self.assertExists(self.chroot_version_file)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -0600169
170 code, output = self._crosSdk(['--snapshot-list'])
171 self.assertEqual(code, 0)
172 self.assertEqual(output.strip(), 'test')
173
174 def testDeleteGoodSnapshot(self):
175 code, _ = self._crosSdk(['--snapshot-create', 'test'])
176 self.assertEqual(code, 0)
177 code, _ = self._crosSdk(['--snapshot-create', 'test2'])
178 self.assertEqual(code, 0)
179
180 code, _ = self._crosSdk(['--snapshot-delete', 'test'])
181 self.assertEqual(code, 0)
182
183 code, output = self._crosSdk(['--snapshot-list'])
184 self.assertEqual(code, 0)
185 self.assertEqual(output.strip(), 'test2')
186
187 def testDeleteMissingSnapshot(self):
188 code, _ = self._crosSdk(['--snapshot-create', 'test'])
189 self.assertEqual(code, 0)
190 code, _ = self._crosSdk(['--snapshot-create', 'test2'])
191 self.assertEqual(code, 0)
192
193 code, _ = self._crosSdk(['--snapshot-delete', 'test3'])
194 self.assertEqual(code, 0)
195
196 code, output = self._crosSdk(['--snapshot-list'])
197 self.assertEqual(code, 0)
198 self.assertSetEqual(set(output.strip().split('\n')), {'test', 'test2'})
199
200 def testDeleteAndCreateSnapshot(self):
201 code, _ = self._crosSdk(['--snapshot-create', 'test'])
202 self.assertEqual(code, 0)
203 code, _ = self._crosSdk(['--snapshot-create', 'test2'])
204 self.assertEqual(code, 0)
205
206 code, _ = self._crosSdk(['--snapshot-create', 'test',
207 '--snapshot-delete', 'test'])
208 self.assertEqual(code, 0)
209
210 code, output = self._crosSdk(['--snapshot-list'])
211 self.assertEqual(code, 0)
212 self.assertSetEqual(set(output.strip().split('\n')), {'test', 'test2'})
213
214 def testRestoreSnapshot(self):
215 with sudo.SudoKeepAlive():
216 test_file = os.path.join(self.chroot, 'etc', 'test_file')
217 osutils.Touch(test_file)
218
219 code, _ = self._crosSdk(['--snapshot-create', 'test'])
220 self.assertEqual(code, 0)
221
222 osutils.SafeUnlink(test_file)
223
224 code, _ = self._crosSdk(['--snapshot-restore', 'test'])
225 self.assertEqual(code, 0)
Benjamin Gordon74645232018-05-04 17:40:42 -0600226 self.assertTrue(cros_sdk_lib.MountChroot(self.chroot, create=False))
Mike Frysingerf2fa7d62017-12-14 18:33:59 -0500227 self.assertExists(test_file)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -0600228
229 code, output = self._crosSdk(['--snapshot-list'])
230 self.assertEqual(code, 0)
231 self.assertEqual(output, '')
232
233 def testRestoreAndCreateSnapshot(self):
234 with sudo.SudoKeepAlive():
235 test_file = os.path.join(self.chroot, 'etc', 'test_file')
236 osutils.Touch(test_file)
237
238 code, _ = self._crosSdk(['--snapshot-create', 'test'])
239 self.assertEqual(code, 0)
240
241 osutils.SafeUnlink(test_file)
242
243 code, _ = self._crosSdk(['--snapshot-restore', 'test',
244 '--snapshot-create', 'test'])
245 self.assertEqual(code, 0)
Benjamin Gordon74645232018-05-04 17:40:42 -0600246 self.assertTrue(cros_sdk_lib.MountChroot(self.chroot, create=False))
Mike Frysingerf2fa7d62017-12-14 18:33:59 -0500247 self.assertExists(test_file)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -0600248
249 code, output = self._crosSdk(['--snapshot-list'])
250 self.assertEqual(code, 0)
251 self.assertEqual(output.strip(), 'test')
252
253 def testDeleteCantRestoreSameSnapshot(self):
254 code, _ = self._crosSdk(['--snapshot-create', 'test'])
255 self.assertEqual(code, 0)
256
257 code, _ = self._crosSdk(['--snapshot-delete', 'test',
258 '--snapshot-restore', 'test'])
259 self.assertNotEqual(code, 0)
260
261 code, output = self._crosSdk(['--snapshot-list'])
262 self.assertEqual(code, 0)
263 self.assertEqual(output.strip(), 'test')
264
265 def testCantRestoreInvalidSnapshot(self):
266 with sudo.SudoKeepAlive():
267 test_file = os.path.join(self.chroot, 'etc', 'test_file')
268 osutils.Touch(test_file)
269
270 code, _ = self._crosSdk(['--snapshot-restore', 'test'])
271 self.assertNotEqual(code, 0)
272 # Failed restore leaves the existing snapshot in place.
Mike Frysingerf2fa7d62017-12-14 18:33:59 -0500273 self.assertExists(test_file)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -0600274
275 def testRestoreSnapshotMountsAsNeeded(self):
276 with sudo.SudoKeepAlive():
277 test_file = os.path.join(self.chroot, 'etc', 'test_file')
278 osutils.Touch(test_file)
279
280 code, _ = self._crosSdk(['--snapshot-create', 'test'])
281 self.assertEqual(code, 0)
282
283 osutils.SafeUnlink(test_file)
284
Benjamin Gordon74645232018-05-04 17:40:42 -0600285 cros_sdk_lib.CleanupChrootMount(self.chroot)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -0600286
287 code, _ = self._crosSdk(['--snapshot-restore', 'test'])
288 self.assertEqual(code, 0)
Mike Frysingerf2fa7d62017-12-14 18:33:59 -0500289 self.assertExists(test_file)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -0600290
291 code, output = self._crosSdk(['--snapshot-list'])
292 self.assertEqual(code, 0)
293 self.assertEqual(output, '')