blob: 1dfca7819dd80492608013d8b31501b6f6723e2a [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
11
12from chromite.lib import cros_build_lib
13from chromite.lib import cros_logging as logging
Benjamin Gordon74645232018-05-04 17:40:42 -060014from chromite.lib import cros_sdk_lib
Benjamin Gordon2d7bf582017-07-12 10:11:26 -060015from chromite.lib import cros_test_lib
16from chromite.lib import osutils
17from chromite.lib import sudo
18
19
Benjamin Gordon03c56e42017-09-11 15:48:39 -040020class CrosSdkPrerequisitesTest(cros_test_lib.TempDirTestCase):
21 """Tests for required packages on the host machine.
22
23 These are not real unit tests. If these tests fail, it means your machine is
24 missing necessary commands to support image-backed chroots. Run cros_sdk in
25 a terminal to get info about what you need to install.
26 """
27
28 def testLvmCommandsPresent(self):
29 """Check for commands from the lvm2 package."""
30 with sudo.SudoKeepAlive():
31 cmd = ['lvs', '--version']
32 result = cros_build_lib.RunCommand(cmd, error_code_ok=True)
33 self.assertEqual(result.returncode, 0)
34
35 def testThinProvisioningToolsPresent(self):
36 """Check for commands from the thin-provisioning-tools package."""
37 with sudo.SudoKeepAlive():
38 cmd = ['thin_check', '-V']
39 result = cros_build_lib.RunCommand(cmd, error_code_ok=True)
40 self.assertEqual(result.returncode, 0)
41
42 def testLosetupCommandPresent(self):
43 """Check for commands from the mount package."""
44 with sudo.SudoKeepAlive():
45 cmd = ['losetup', '--help']
46 result = cros_build_lib.RunCommand(cmd, error_code_ok=True)
47 self.assertEqual(result.returncode, 0)
48
49
Benjamin Gordon2d7bf582017-07-12 10:11:26 -060050# TODO(bmgordon): Figure out how to mock out --create and --enter and then
51# add tests that combine those with snapshots.
52class CrosSdkSnapshotTest(cros_test_lib.TempDirTestCase):
53 """Tests for the snapshot functionality in cros_sdk."""
54
55 def setUp(self):
56 with sudo.SudoKeepAlive():
57 # Create just enough of a chroot to fool cros_sdk into accepting it.
58 self.chroot = os.path.join(self.tempdir, 'chroot')
Benjamin Gordon74645232018-05-04 17:40:42 -060059 cros_sdk_lib.MountChroot(self.chroot, create=True)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -060060 logging.debug('Chroot mounted on %s', self.chroot)
61
62 chroot_etc = os.path.join(self.chroot, 'etc')
63 osutils.SafeMakedirsNonRoot(chroot_etc)
64
65 self.chroot_version_file = os.path.join(chroot_etc, 'cros_chroot_version')
66 osutils.Touch(self.chroot_version_file, makedirs=True)
67
68 def tearDown(self):
69 with sudo.SudoKeepAlive():
Don Garrett36650112018-06-28 15:54:34 -070070 cros_sdk_lib.CleanupChrootMount(self.chroot, delete=True)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -060071
72 def _crosSdk(self, args):
73 cmd = ['cros_sdk', '--chroot', self.chroot]
74 cmd.extend(args)
75
76 try:
77 result = cros_build_lib.RunCommand(
78 cmd, print_cmd=False, capture_output=True, error_code_ok=True,
79 combine_stdout_stderr=True)
80 except cros_build_lib.RunCommandError as e:
81 raise SystemExit('Running %r failed!: %s' % (cmd, e))
82
83 return result.returncode, result.output
84
85 def testSnapshotsRequireImage(self):
86 code, output = self._crosSdk(['--snapshot-list', '--nouse-image'])
87 self.assertNotEqual(code, 0)
88 self.assertIn('Snapshot operations are not compatible with', output)
89
90 code, output = self._crosSdk(['--snapshot-delete', 'test', '--nouse-image'])
91 self.assertNotEqual(code, 0)
92 self.assertIn('Snapshot operations are not compatible with', output)
93
94 code, output = self._crosSdk(['--snapshot-create', 'test', '--nouse-image'])
95 self.assertNotEqual(code, 0)
96 self.assertIn('Snapshot operations are not compatible with', output)
97
98 code, output = self._crosSdk(['--snapshot-restore', 'test',
99 '--nouse-image'])
100 self.assertNotEqual(code, 0)
101 self.assertIn('Snapshot operations are not compatible with', output)
102
103 def testSnapshotWithDeleteChroot(self):
104 code, output = self._crosSdk(['--delete', '--snapshot-list'])
105 self.assertNotEqual(code, 0)
106 self.assertIn('Trying to enter or snapshot the chroot', output)
107
108 code, output = self._crosSdk(['--delete', '--snapshot-delete', 'test'])
109 self.assertNotEqual(code, 0)
110 self.assertIn('Trying to enter or snapshot the chroot', output)
111
112 code, output = self._crosSdk(['--delete', '--snapshot-create', 'test'])
113 self.assertNotEqual(code, 0)
114 self.assertIn('Trying to enter or snapshot the chroot', output)
115
116 code, output = self._crosSdk(['--delete', '--snapshot-restore', 'test'])
117 self.assertNotEqual(code, 0)
118 self.assertIn('Trying to enter or snapshot the chroot', output)
119
120 def testEmptySnapshotList(self):
121 code, output = self._crosSdk(['--snapshot-list'])
122 self.assertEqual(code, 0)
123 self.assertEqual(output, '')
124
125 def testOneSnapshot(self):
126 code, _ = self._crosSdk(['--snapshot-create', 'test'])
127 self.assertEqual(code, 0)
128
129 code, output = self._crosSdk(['--snapshot-list'])
130 self.assertEqual(code, 0)
131 self.assertEqual(output.strip(), 'test')
132
133 def testMultipleSnapshots(self):
134 code, _ = self._crosSdk(['--snapshot-create', 'test'])
135 self.assertEqual(code, 0)
136 code, _ = self._crosSdk(['--snapshot-create', 'test2'])
137 self.assertEqual(code, 0)
138
139 code, output = self._crosSdk(['--snapshot-list'])
140 self.assertEqual(code, 0)
141 self.assertSetEqual(set(output.strip().split('\n')), {'test', 'test2'})
142
143 def testCantCreateSameSnapshotTwice(self):
144 code, _ = self._crosSdk(['--snapshot-create', 'test'])
145 self.assertEqual(code, 0)
146 code, _ = self._crosSdk(['--snapshot-create', 'test'])
147 self.assertNotEqual(code, 0)
148
149 code, output = self._crosSdk(['--snapshot-list'])
150 self.assertEqual(code, 0)
151 self.assertEqual(output.strip(), 'test')
152
153 def testCreateSnapshotMountsAsNeeded(self):
154 with sudo.SudoKeepAlive():
Benjamin Gordon74645232018-05-04 17:40:42 -0600155 cros_sdk_lib.CleanupChrootMount(self.chroot)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -0600156
157 code, _ = self._crosSdk(['--snapshot-create', 'test'])
158 self.assertEqual(code, 0)
Mike Frysingerf2fa7d62017-12-14 18:33:59 -0500159 self.assertExists(self.chroot_version_file)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -0600160
161 code, output = self._crosSdk(['--snapshot-list'])
162 self.assertEqual(code, 0)
163 self.assertEqual(output.strip(), 'test')
164
165 def testDeleteGoodSnapshot(self):
166 code, _ = self._crosSdk(['--snapshot-create', 'test'])
167 self.assertEqual(code, 0)
168 code, _ = self._crosSdk(['--snapshot-create', 'test2'])
169 self.assertEqual(code, 0)
170
171 code, _ = self._crosSdk(['--snapshot-delete', 'test'])
172 self.assertEqual(code, 0)
173
174 code, output = self._crosSdk(['--snapshot-list'])
175 self.assertEqual(code, 0)
176 self.assertEqual(output.strip(), 'test2')
177
178 def testDeleteMissingSnapshot(self):
179 code, _ = self._crosSdk(['--snapshot-create', 'test'])
180 self.assertEqual(code, 0)
181 code, _ = self._crosSdk(['--snapshot-create', 'test2'])
182 self.assertEqual(code, 0)
183
184 code, _ = self._crosSdk(['--snapshot-delete', 'test3'])
185 self.assertEqual(code, 0)
186
187 code, output = self._crosSdk(['--snapshot-list'])
188 self.assertEqual(code, 0)
189 self.assertSetEqual(set(output.strip().split('\n')), {'test', 'test2'})
190
191 def testDeleteAndCreateSnapshot(self):
192 code, _ = self._crosSdk(['--snapshot-create', 'test'])
193 self.assertEqual(code, 0)
194 code, _ = self._crosSdk(['--snapshot-create', 'test2'])
195 self.assertEqual(code, 0)
196
197 code, _ = self._crosSdk(['--snapshot-create', 'test',
198 '--snapshot-delete', 'test'])
199 self.assertEqual(code, 0)
200
201 code, output = self._crosSdk(['--snapshot-list'])
202 self.assertEqual(code, 0)
203 self.assertSetEqual(set(output.strip().split('\n')), {'test', 'test2'})
204
205 def testRestoreSnapshot(self):
206 with sudo.SudoKeepAlive():
207 test_file = os.path.join(self.chroot, 'etc', 'test_file')
208 osutils.Touch(test_file)
209
210 code, _ = self._crosSdk(['--snapshot-create', 'test'])
211 self.assertEqual(code, 0)
212
213 osutils.SafeUnlink(test_file)
214
215 code, _ = self._crosSdk(['--snapshot-restore', 'test'])
216 self.assertEqual(code, 0)
Benjamin Gordon74645232018-05-04 17:40:42 -0600217 self.assertTrue(cros_sdk_lib.MountChroot(self.chroot, create=False))
Mike Frysingerf2fa7d62017-12-14 18:33:59 -0500218 self.assertExists(test_file)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -0600219
220 code, output = self._crosSdk(['--snapshot-list'])
221 self.assertEqual(code, 0)
222 self.assertEqual(output, '')
223
224 def testRestoreAndCreateSnapshot(self):
225 with sudo.SudoKeepAlive():
226 test_file = os.path.join(self.chroot, 'etc', 'test_file')
227 osutils.Touch(test_file)
228
229 code, _ = self._crosSdk(['--snapshot-create', 'test'])
230 self.assertEqual(code, 0)
231
232 osutils.SafeUnlink(test_file)
233
234 code, _ = self._crosSdk(['--snapshot-restore', 'test',
235 '--snapshot-create', 'test'])
236 self.assertEqual(code, 0)
Benjamin Gordon74645232018-05-04 17:40:42 -0600237 self.assertTrue(cros_sdk_lib.MountChroot(self.chroot, create=False))
Mike Frysingerf2fa7d62017-12-14 18:33:59 -0500238 self.assertExists(test_file)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -0600239
240 code, output = self._crosSdk(['--snapshot-list'])
241 self.assertEqual(code, 0)
242 self.assertEqual(output.strip(), 'test')
243
244 def testDeleteCantRestoreSameSnapshot(self):
245 code, _ = self._crosSdk(['--snapshot-create', 'test'])
246 self.assertEqual(code, 0)
247
248 code, _ = self._crosSdk(['--snapshot-delete', 'test',
249 '--snapshot-restore', 'test'])
250 self.assertNotEqual(code, 0)
251
252 code, output = self._crosSdk(['--snapshot-list'])
253 self.assertEqual(code, 0)
254 self.assertEqual(output.strip(), 'test')
255
256 def testCantRestoreInvalidSnapshot(self):
257 with sudo.SudoKeepAlive():
258 test_file = os.path.join(self.chroot, 'etc', 'test_file')
259 osutils.Touch(test_file)
260
261 code, _ = self._crosSdk(['--snapshot-restore', 'test'])
262 self.assertNotEqual(code, 0)
263 # Failed restore leaves the existing snapshot in place.
Mike Frysingerf2fa7d62017-12-14 18:33:59 -0500264 self.assertExists(test_file)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -0600265
266 def testRestoreSnapshotMountsAsNeeded(self):
267 with sudo.SudoKeepAlive():
268 test_file = os.path.join(self.chroot, 'etc', 'test_file')
269 osutils.Touch(test_file)
270
271 code, _ = self._crosSdk(['--snapshot-create', 'test'])
272 self.assertEqual(code, 0)
273
274 osutils.SafeUnlink(test_file)
275
Benjamin Gordon74645232018-05-04 17:40:42 -0600276 cros_sdk_lib.CleanupChrootMount(self.chroot)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -0600277
278 code, _ = self._crosSdk(['--snapshot-restore', 'test'])
279 self.assertEqual(code, 0)
Mike Frysingerf2fa7d62017-12-14 18:33:59 -0500280 self.assertExists(test_file)
Benjamin Gordon2d7bf582017-07-12 10:11:26 -0600281
282 code, output = self._crosSdk(['--snapshot-list'])
283 self.assertEqual(code, 0)
284 self.assertEqual(output, '')