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