blob: 795d8e4cc207a0167ed3ba13db9de01429a90976 [file] [log] [blame]
Ryan Cuiafd6c5c2012-07-30 17:48:22 -07001#!/usr/bin/python
2# Copyright (c) 2012 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
Ryan Cuiafd6c5c2012-07-30 17:48:22 -07007import os
8import sys
9
10sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)),
11 '..', '..'))
Ryan Cuief91e702013-02-04 12:06:36 -080012
13from chromite.lib import chrome_util
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070014from chromite.lib import cros_build_lib
15from chromite.lib import cros_test_lib
16from chromite.lib import partial_mock
17from chromite.lib import remote_access_unittest
18from chromite.scripts import deploy_chrome
19
Ryan Cuief91e702013-02-04 12:06:36 -080020
Brian Harringe7524372012-12-23 02:02:56 -080021# TODO(build): Finish test wrapper (http://crosbug.com/37517).
22# Until then, this has to be after the chromite imports.
23import mock
24
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070025
26# pylint: disable=W0212
27
28_REGULAR_TO = ('--to', 'monkey')
29_GS_PATH = 'gs://foon'
30
31
32def _ParseCommandLine(argv):
33 return deploy_chrome._ParseCommandLine(['--log-level', 'debug'] + argv)
34
35
36class InterfaceTest(cros_test_lib.OutputTestCase):
37 """Tests the commandline interface of the script."""
38
39 def testGsLocalPathUnSpecified(self):
40 """Test no chrome path specified."""
41 with self.OutputCapturer():
42 self.assertRaises2(SystemExit, _ParseCommandLine, list(_REGULAR_TO),
43 check_attrs={'code': 2})
44
45 def testGsPathSpecified(self):
46 """Test case of GS path specified."""
47 argv = list(_REGULAR_TO) + ['--gs-path', _GS_PATH]
48 _ParseCommandLine(argv)
49
50 def testLocalPathSpecified(self):
51 """Test case of local path specified."""
Ryan Cuia56a71e2012-10-18 18:40:35 -070052 argv = list(_REGULAR_TO) + ['--local-pkg-path', '/path/to/chrome']
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070053 _ParseCommandLine(argv)
54
55 def testNoTarget(self):
56 """Test no target specified."""
57 argv = ['--gs-path', _GS_PATH]
Ryan Cuief91e702013-02-04 12:06:36 -080058 self.assertParseError(argv)
59
60 def assertParseError(self, argv):
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070061 with self.OutputCapturer():
62 self.assertRaises2(SystemExit, _ParseCommandLine, argv,
63 check_attrs={'code': 2})
64
Ryan Cuief91e702013-02-04 12:06:36 -080065 def testStagingFlagsNoStrict(self):
66 """Errors out when --staging-flags is set without --strict."""
67 argv = ['--staging-only', '--build-dir=/path/to/nowhere',
68 '--staging-flags=highdpi']
69 self.assertParseError(argv)
70
71 def testStrictNoBuildDir(self):
72 """Errors out when --strict is set without --build-dir."""
73 argv = ['--staging-only', '--strict', '--gs-path', _GS_PATH]
74 self.assertParseError(argv)
75
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070076
77class DeployChromeMock(partial_mock.PartialMock):
78
79 TARGET = 'chromite.scripts.deploy_chrome.DeployChrome'
80 ATTRS = ('_CheckRootfsWriteable', '_DisableRootfsVerification',
81 '_KillProcsIfNeeded')
82
Ryan Cuie18f24f2012-12-03 18:39:55 -080083 def __init__(self, disable_ok=True):
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070084 partial_mock.PartialMock.__init__(self)
85 self.disable_ok = disable_ok
86 self.rootfs_writeable = False
87 # Target starts off as having rootfs verification enabled.
Ryan Cuie18f24f2012-12-03 18:39:55 -080088 self.rsh_mock = remote_access_unittest.RemoteShMock()
Ryan Cuiafd6c5c2012-07-30 17:48:22 -070089 self.MockMountCmd(1)
90
91 def MockMountCmd(self, returnvalue):
92 def hook(_inst, *_args, **_kwargs):
93 self.rootfs_writeable = True
94
95 self.rsh_mock.AddCmdResult(deploy_chrome.MOUNT_RW_COMMAND,
96 returnvalue,
97 side_effect=None if returnvalue else hook)
98
Ryan Cui4d6fca92012-12-13 16:41:56 -080099 def PreStart(self):
100 self.rsh_mock.start()
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700101
Ryan Cui4d6fca92012-12-13 16:41:56 -0800102 def PreStop(self):
103 self.rsh_mock.stop()
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700104
105 def _CheckRootfsWriteable(self, _inst):
106 return self.rootfs_writeable
107
108 def _DisableRootfsVerification(self, _inst):
109 self.MockMountCmd(int(not self.disable_ok))
110
111 def _KillProcsIfNeeded(self, _inst):
112 # Fully stub out for now.
113 pass
114
115
Ryan Cuief91e702013-02-04 12:06:36 -0800116class DeployTest(cros_test_lib.MockTempDirTestCase):
117 def _GetDeployChrome(self, args):
118 options, _ = _ParseCommandLine(args)
Ryan Cuia56a71e2012-10-18 18:40:35 -0700119 return deploy_chrome.DeployChrome(
120 options, self.tempdir, os.path.join(self.tempdir, 'staging'))
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700121
122 def setUp(self):
Ryan Cuif1416f32013-01-22 18:43:41 -0800123 self.deploy_mock = self.StartPatcher(DeployChromeMock())
Ryan Cuief91e702013-02-04 12:06:36 -0800124 self.deploy = self._GetDeployChrome(
125 list(_REGULAR_TO) + ['--gs-path', _GS_PATH])
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700126
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700127
Ryan Cuief91e702013-02-04 12:06:36 -0800128class TestPrepareTarget(DeployTest):
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700129 """Testing disabling of rootfs verification and RO mode."""
130
131 def testSuccess(self):
132 """Test the working case."""
133 self.deploy._PrepareTarget()
134
135 def testDisableRootfsVerificationFailure(self):
136 """Test failure to disable rootfs verification."""
137 self.deploy_mock.disable_ok = False
138 self.assertRaises(cros_build_lib.RunCommandError,
139 self.deploy._PrepareTarget)
140
141 def testMountRwFailure(self):
142 """The mount command returncode was 0 but rootfs is still readonly."""
143 with mock.patch.object(deploy_chrome.DeployChrome, '_CheckRootfsWriteable',
144 auto_spec=True) as m:
145 m.return_value = False
146 self.assertRaises(SystemExit, self.deploy._PrepareTarget)
147
148 def testMountRwSuccessFirstTime(self):
149 """We were able to mount as RW the first time."""
150 self.deploy_mock.MockMountCmd(0)
151 self.deploy._PrepareTarget()
152
153
154PROC_MOUNTS = """\
155rootfs / rootfs rw 0 0
156/dev/root / ext2 %s,relatime,user_xattr,acl 0 0
157devtmpfs /dev devtmpfs rw,relatime,size=970032k,nr_inodes=242508,mode=755 0 0
158none /proc proc rw,nosuid,nodev,noexec,relatime 0 0
159"""
160
161
Ryan Cuief91e702013-02-04 12:06:36 -0800162class TestCheckRootfs(DeployTest):
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700163 """Test Rootfs RW check functionality."""
164
165 def setUp(self):
166 self.deploy_mock.UnMockAttr('_CheckRootfsWriteable')
167
168 def MockProcMountsCmd(self, output):
169 self.deploy_mock.rsh_mock.AddCmdResult('cat /proc/mounts', output=output)
170
171 def testCheckRootfsWriteableFalse(self):
172 """Correct results with RO."""
173 self.MockProcMountsCmd(PROC_MOUNTS % 'ro')
174 self.assertFalse(self.deploy._CheckRootfsWriteable())
175
176 def testCheckRootfsWriteableTrue(self):
177 """Correct results with RW."""
178 self.MockProcMountsCmd(PROC_MOUNTS % 'rw')
179 self.assertTrue(self.deploy._CheckRootfsWriteable())
180
181
Ryan Cuief91e702013-02-04 12:06:36 -0800182class TestUiJobStarted(DeployTest):
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700183 """Test detection of a running 'ui' job."""
184
185 def MockStatusUiCmd(self, output):
186 self.deploy_mock.rsh_mock.AddCmdResult('status ui', output=output)
187
188 def testUiJobStartedFalse(self):
189 """Correct results with a stopped job."""
190 self.MockStatusUiCmd('ui stop/waiting')
191 self.assertFalse(self.deploy._CheckUiJobStarted())
192
193 def testCheckRootfsWriteableTrue(self):
194 """Correct results with a running job."""
195 self.MockStatusUiCmd('ui start/running, process 297')
196 self.assertTrue(self.deploy._CheckUiJobStarted())
197
198
Ryan Cuief91e702013-02-04 12:06:36 -0800199class StagingTest(cros_test_lib.MockTempDirTestCase):
200 """Test user-mode and ebuild-mode staging functionality."""
201
202 def setUp(self):
203 self.sudo_cleanup = True
204 self.staging_dir = os.path.join(self.tempdir, 'staging')
205 self.build_dir = os.path.join(self.tempdir, 'build_dir')
206 self.common_flags = ['--build-dir', self.build_dir, '--staging-only']
207
208 def testEmptyDeploySuccess(self):
209 """User-mode staging - stage whatever we can find."""
210 options, _ = _ParseCommandLine(self.common_flags)
211 deploy_chrome._PrepareStagingDir(
212 options, self.tempdir, self.staging_dir)
213
214 def testEmptyDeployStrict(self):
215 """ebuild-mode staging - stage only things we want."""
216 options, _ = _ParseCommandLine(
217 self.common_flags + ['--gyp-defines', 'chromeos=1', '--strict'])
218 self.assertRaises(
219 chrome_util.MissingPathError, deploy_chrome._PrepareStagingDir,
220 options, self.tempdir, self.staging_dir)
221
222
Ryan Cuiafd6c5c2012-07-30 17:48:22 -0700223if __name__ == '__main__':
224 cros_test_lib.main()