• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2018 - The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""Tests for remote_image_local_instance."""
15
16import unittest
17from collections import namedtuple
18import os
19import subprocess
20import mock
21
22from acloud import errors
23from acloud.create.remote_image_local_instance import RemoteImageLocalInstance
24from acloud.internal.lib import android_build_client
25from acloud.internal.lib import auth
26from acloud.internal.lib import driver_test_lib
27from acloud.internal.lib import utils
28from acloud.setup import setup_common
29
30
31# pylint: disable=invalid-name, protected-access
32class RemoteImageLocalInstanceTest(driver_test_lib.BaseDriverTest):
33    """Test remote_image_local_instance methods."""
34
35    def setUp(self):
36        """Initialize remote_image_local_instance."""
37        super(RemoteImageLocalInstanceTest, self).setUp()
38        self.build_client = mock.MagicMock()
39        self.Patch(
40            android_build_client,
41            "AndroidBuildClient",
42            return_value=self.build_client)
43        self.Patch(auth, "CreateCredentials", return_value=mock.MagicMock())
44        self.RemoteImageLocalInstance = RemoteImageLocalInstance()
45        self._fake_remote_image = {"build_target" : "aosp_cf_x86_phone-userdebug",
46                                   "build_id": "1234"}
47        self._extract_path = "/tmp/acloud_image_artifacts/1234"
48
49    @mock.patch.object(RemoteImageLocalInstance, "_DownloadAndProcessImageFiles")
50    def testGetImageArtifactsPath(self, mock_proc):
51        """Test get image artifacts path."""
52        avd_spec = mock.MagicMock()
53        # raise errors.NoCuttlefishCommonInstalled
54        self.Patch(setup_common, "PackageInstalled", return_value=False)
55        self.assertRaises(errors.NoCuttlefishCommonInstalled,
56                          self.RemoteImageLocalInstance.GetImageArtifactsPath,
57                          avd_spec)
58
59        # Valid _DownloadAndProcessImageFiles run.
60        self.Patch(setup_common, "PackageInstalled", return_value=True)
61        self.Patch(self.RemoteImageLocalInstance,
62                   "_ConfirmDownloadRemoteImageDir", return_value="/tmp")
63        self.Patch(os.path, "exists", return_value=True)
64        self.RemoteImageLocalInstance.GetImageArtifactsPath(avd_spec)
65        mock_proc.assert_called_once_with(avd_spec)
66
67    @mock.patch.object(RemoteImageLocalInstance, "_AclCfImageFiles")
68    @mock.patch.object(RemoteImageLocalInstance, "_UnpackBootImage")
69    @mock.patch.object(RemoteImageLocalInstance, "_DownloadRemoteImage")
70    def testDownloadAndProcessImageFiles(self, mock_download, mock_unpack, mock_acl):
71        """Test process remote cuttlefish image."""
72        avd_spec = mock.MagicMock()
73        avd_spec.cfg = mock.MagicMock()
74        avd_spec.remote_image = self._fake_remote_image
75        avd_spec.image_download_dir = "/tmp"
76        self.Patch(os.path, "exists", return_value=False)
77        self.Patch(os, "makedirs")
78        self.RemoteImageLocalInstance._DownloadAndProcessImageFiles(avd_spec)
79
80        # To make sure each function execute once.
81        mock_download.assert_called_once_with(
82            avd_spec.cfg,
83            avd_spec.remote_image["build_target"],
84            avd_spec.remote_image["build_id"],
85            self._extract_path)
86        mock_unpack.assert_called_once_with(self._extract_path)
87        mock_acl.assert_called_once_with(self._extract_path)
88
89    @mock.patch.object(utils, "Decompress")
90    def testDownloadRemoteImage(self, mock_decompress):
91        """Test Download cuttlefish package."""
92        avd_spec = mock.MagicMock()
93        avd_spec.cfg = mock.MagicMock()
94        avd_spec.remote_image = self._fake_remote_image
95        build_id = "1234"
96        build_target = "aosp_cf_x86_phone-userdebug"
97        checkfile1 = "aosp_cf_x86_phone-img-1234.zip"
98        checkfile2 = "cvd-host_package.tar.gz"
99
100        self.RemoteImageLocalInstance._DownloadRemoteImage(
101            avd_spec.cfg,
102            avd_spec.remote_image["build_target"],
103            avd_spec.remote_image["build_id"],
104            self._extract_path)
105
106        # To validate DownloadArtifact runs twice.
107        self.assertEqual(self.build_client.DownloadArtifact.call_count, 2)
108        # To validate DownloadArtifact arguments correct.
109        self.build_client.DownloadArtifact.assert_has_calls([
110            mock.call(build_target, build_id, checkfile1,
111                      "%s/%s" % (self._extract_path, checkfile1)),
112            mock.call(build_target, build_id, checkfile2,
113                      "%s/%s" % (self._extract_path, checkfile2))],
114                                                            any_order=True)
115        # To validate Decompress runs twice.
116        self.assertEqual(mock_decompress.call_count, 2)
117
118    @mock.patch.object(subprocess, "check_call")
119    def testUnpackBootImage(self, mock_call):
120        """Test Unpack boot image."""
121        self.Patch(os.path, "exists", side_effect=[True, False])
122        self.RemoteImageLocalInstance._UnpackBootImage(self._extract_path)
123        # check_call run once when boot.img exist.
124        self.assertEqual(mock_call.call_count, 1)
125        # raise errors.BootImgDoesNotExist when boot.img doesn't exist.
126        self.assertRaises(errors.BootImgDoesNotExist,
127                          self.RemoteImageLocalInstance._UnpackBootImage,
128                          self._extract_path)
129
130    def testConfirmDownloadRemoteImageDir(self):
131        """Test confirm download remote image dir"""
132        self.Patch(os.path, "exists", return_value=True)
133        self.Patch(os, "makedirs")
134        # Default minimum avail space should be more than 10G
135        # then return download_dir directly.
136        self.Patch(os, "statvfs", return_value=namedtuple(
137            "statvfs", "f_bavail, f_bsize")(11, 1073741824))
138        download_dir = "/tmp"
139        self.assertEqual(
140            self.RemoteImageLocalInstance._ConfirmDownloadRemoteImageDir(
141                download_dir), "/tmp")
142
143        # Test when insuficient disk space and input 'q' to exit.
144        self.Patch(os, "statvfs", return_value=namedtuple(
145            "statvfs", "f_bavail, f_bsize")(9, 1073741824))
146        self.Patch(utils, "InteractWithQuestion", return_value="q")
147        self.assertRaises(SystemExit,
148                          self.RemoteImageLocalInstance._ConfirmDownloadRemoteImageDir,
149                          download_dir)
150
151        # If avail space detect as 9GB, and 2nd input 7GB both less than 10GB
152        # 3rd input over 10GB, so return path should be "/tmp3".
153        self.Patch(os, "statvfs", side_effect=[
154            namedtuple("statvfs", "f_bavail, f_bsize")(9, 1073741824),
155            namedtuple("statvfs", "f_bavail, f_bsize")(7, 1073741824),
156            namedtuple("statvfs", "f_bavail, f_bsize")(11, 1073741824)])
157        self.Patch(utils, "InteractWithQuestion", side_effect=["/tmp2",
158                                                               "/tmp3"])
159        self.assertEqual(
160            self.RemoteImageLocalInstance._ConfirmDownloadRemoteImageDir(
161                download_dir), "/tmp3")
162
163        # Test when path not exist, define --image-download-dir
164        # enter anything else to exit out.
165        download_dir = "/image_download_dir1"
166        self.Patch(os.path, "exists", return_value=False)
167        self.Patch(utils, "InteractWithQuestion", return_value="")
168        self.assertRaises(SystemExit,
169                          self.RemoteImageLocalInstance._ConfirmDownloadRemoteImageDir,
170                          download_dir)
171
172        # Test using --image-dowload-dir and makedirs.
173        # enter 'y' to create it.
174        self.Patch(utils, "InteractWithQuestion", return_value="y")
175        self.Patch(os, "statvfs", return_value=namedtuple(
176            "statvfs", "f_bavail, f_bsize")(10, 1073741824))
177        self.assertEqual(
178            self.RemoteImageLocalInstance._ConfirmDownloadRemoteImageDir(
179                download_dir), "/image_download_dir1")
180
181        # Test when 1st check fails for insufficient disk space, user inputs an
182        # alternate dir but it doesn't exist and the user choose to exit.
183        self.Patch(os, "statvfs", side_effect=[
184            namedtuple("statvfs", "f_bavail, f_bsize")(9, 1073741824),
185            namedtuple("statvfs", "f_bavail, f_bsize")(11, 1073741824)])
186        self.Patch(os.path, "exists", side_effect=[True, False])
187        self.Patch(utils, "InteractWithQuestion",
188                   side_effect=["~/nopath", "not_y"])
189        self.assertRaises(
190            SystemExit,
191            self.RemoteImageLocalInstance._ConfirmDownloadRemoteImageDir,
192            download_dir)
193
194        # Test when 1st check fails for insufficient disk space, user inputs an
195        # alternate dir but it doesn't exist and they request to create it.
196        self.Patch(os, "statvfs", side_effect=[
197            namedtuple("statvfs", "f_bavail, f_bsize")(9, 1073741824),
198            namedtuple("statvfs", "f_bavail, f_bsize")(10, 1073741824)])
199        self.Patch(os.path, "exists", side_effect=[True, False])
200        self.Patch(utils, "InteractWithQuestion", side_effect=["~/nopath", "y"])
201        self.assertEqual(
202            self.RemoteImageLocalInstance._ConfirmDownloadRemoteImageDir(
203                download_dir), os.path.expanduser("~/nopath"))
204
205
206if __name__ == "__main__":
207    unittest.main()
208