• 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 avd_spec."""
15
16import glob
17import os
18import subprocess
19import unittest
20import mock
21
22from acloud import errors
23from acloud.create import avd_spec
24from acloud.internal import constants
25from acloud.internal.lib import android_build_client
26from acloud.internal.lib import auth
27from acloud.internal.lib import driver_test_lib
28from acloud.internal.lib import utils
29from acloud.list import list as list_instances
30
31
32# pylint: disable=invalid-name,protected-access
33class AvdSpecTest(driver_test_lib.BaseDriverTest):
34    """Test avd_spec methods."""
35
36    def setUp(self):
37        """Initialize new avd_spec.AVDSpec."""
38        super(AvdSpecTest, self).setUp()
39        self.args = mock.MagicMock()
40        self.args.flavor = ""
41        self.args.local_image = ""
42        self.args.config_file = ""
43        self.args.build_target = "fake_build_target"
44        self.args.adb_port = None
45        self.Patch(list_instances, "ChooseOneRemoteInstance", return_value=mock.MagicMock())
46        self.Patch(list_instances, "GetInstancesFromInstanceNames", return_value=mock.MagicMock())
47        self.AvdSpec = avd_spec.AVDSpec(self.args)
48
49    # pylint: disable=protected-access
50    def testProcessLocalImageArgs(self):
51        """Test process args.local_image."""
52        self.Patch(glob, "glob", return_value=["fake.img"])
53        expected_image_artifact = "/path/cf_x86_phone-img-eng.user.zip"
54        expected_image_dir = "/path-to-image-dir"
55
56        # Specified --local-image to a local zipped image file
57        self.Patch(os.path, "isfile", return_value=True)
58        self.args.local_image = "/path/cf_x86_phone-img-eng.user.zip"
59        self.AvdSpec._avd_type = constants.TYPE_CF
60        self.AvdSpec._instance_type = constants.INSTANCE_TYPE_REMOTE
61        self.AvdSpec._ProcessLocalImageArgs(self.args)
62        self.assertEqual(self.AvdSpec._local_image_artifact,
63                         expected_image_artifact)
64
65        # Specified --local-image to a dir contains images
66        self.Patch(utils, "GetBuildEnvironmentVariable",
67                   return_value="test_environ")
68        self.Patch(os.path, "isfile", return_value=False)
69        self.args.local_image = "/path-to-image-dir"
70        self.AvdSpec._avd_type = constants.TYPE_CF
71        self.AvdSpec._instance_type = constants.INSTANCE_TYPE_REMOTE
72        self.AvdSpec._ProcessLocalImageArgs(self.args)
73        self.assertEqual(self.AvdSpec._local_image_dir, expected_image_dir)
74
75        # Specified local_image without arg
76        self.args.local_image = None
77        self.Patch(utils, "GetBuildEnvironmentVariable",
78                   return_value="test_environ")
79        self.AvdSpec._ProcessLocalImageArgs(self.args)
80        self.assertEqual(self.AvdSpec._local_image_dir, "test_environ")
81        self.assertEqual(self.AvdSpec.local_image_artifact, expected_image_artifact)
82
83        # Specified --avd-type=goldfish --local-image with a dir
84        self.Patch(utils, "GetBuildEnvironmentVariable",
85                   return_value="test_environ")
86        self.Patch(os.path, "isdir", return_value=True)
87        self.args.local_image = "/path-to-image-dir"
88        self.AvdSpec._avd_type = constants.TYPE_GF
89        self.AvdSpec._instance_type = constants.INSTANCE_TYPE_LOCAL
90        self.AvdSpec._ProcessLocalImageArgs(self.args)
91        self.assertEqual(self.AvdSpec._local_image_dir, expected_image_dir)
92
93        # Specified --avd-type=goldfish --local_image without arg
94        self.Patch(utils, "GetBuildEnvironmentVariable",
95                   return_value="test_environ")
96        self.Patch(os.path, "isdir", return_value=True)
97        self.args.local_image = None
98        self.AvdSpec._avd_type = constants.TYPE_GF
99        self.AvdSpec._instance_type = constants.INSTANCE_TYPE_LOCAL
100        self.AvdSpec._ProcessLocalImageArgs(self.args)
101        self.assertEqual(self.AvdSpec._local_image_dir, "test_environ")
102
103    def testProcessImageArgs(self):
104        """Test process image source."""
105        self.Patch(glob, "glob", return_value=["fake.img"])
106        # No specified local_image, image source is from remote
107        self.args.local_image = ""
108        self.AvdSpec._ProcessImageArgs(self.args)
109        self.assertEqual(self.AvdSpec._image_source, constants.IMAGE_SRC_REMOTE)
110        self.assertEqual(self.AvdSpec._local_image_dir, None)
111
112        # Specified local_image with an arg for cf type
113        self.Patch(os.path, "isfile", return_value=True)
114        self.args.local_image = "/test_path/cf_x86_phone-img-eng.user.zip"
115        self.AvdSpec._avd_type = constants.TYPE_CF
116        self.AvdSpec._instance_type = constants.INSTANCE_TYPE_REMOTE
117        self.AvdSpec._ProcessImageArgs(self.args)
118        self.assertEqual(self.AvdSpec._image_source, constants.IMAGE_SRC_LOCAL)
119        self.assertEqual(self.AvdSpec._local_image_artifact,
120                         "/test_path/cf_x86_phone-img-eng.user.zip")
121
122        # Specified local_image with an arg for gce type
123        self.Patch(os.path, "isfile", return_value=False)
124        self.Patch(os.path, "exists", return_value=True)
125        self.args.local_image = "/test_path_to_dir/"
126        self.AvdSpec._avd_type = constants.TYPE_GCE
127        self.AvdSpec._ProcessImageArgs(self.args)
128        self.assertEqual(self.AvdSpec._image_source, constants.IMAGE_SRC_LOCAL)
129        self.assertEqual(self.AvdSpec._local_image_artifact,
130                         "/test_path_to_dir/avd-system.tar.gz")
131
132    @mock.patch.object(avd_spec.AVDSpec, "_GetGitRemote")
133    def testGetBranchFromRepo(self, mock_gitremote):
134        """Test get branch name from repo info."""
135        # Check aosp repo gets proper branch prefix.
136        fake_subprocess = mock.MagicMock()
137        fake_subprocess.stdout = mock.MagicMock()
138        fake_subprocess.stdout.readline = mock.MagicMock(return_value='')
139        fake_subprocess.poll = mock.MagicMock(return_value=0)
140        fake_subprocess.returncode = 0
141        return_value = "Manifest branch: master"
142        fake_subprocess.communicate = mock.MagicMock(return_value=(return_value, ''))
143        self.Patch(subprocess, "Popen", return_value=fake_subprocess)
144
145        mock_gitremote.return_value = "aosp"
146        self.assertEqual(self.AvdSpec._GetBranchFromRepo(), "aosp-master")
147
148        # Check default repo gets default branch prefix.
149        mock_gitremote.return_value = ""
150        return_value = "Manifest branch: master"
151        fake_subprocess.communicate = mock.MagicMock(return_value=(return_value, ''))
152        self.Patch(subprocess, "Popen", return_value=fake_subprocess)
153        self.assertEqual(self.AvdSpec._GetBranchFromRepo(), "git_master")
154
155        # Can't get branch from repo info, set it as default branch.
156        return_value = "Manifest branch:"
157        fake_subprocess.communicate = mock.MagicMock(return_value=(return_value, ''))
158        self.Patch(subprocess, "Popen", return_value=fake_subprocess)
159        self.assertEqual(self.AvdSpec._GetBranchFromRepo(), "aosp-master")
160
161    def testGetBuildBranch(self):
162        """Test GetBuildBranch function"""
163        # Test infer branch from build_id and build_target.
164        build_client = mock.MagicMock()
165        build_id = "fake_build_id"
166        build_target = "fake_build_target"
167        expected_branch = "fake_build_branch"
168        self.Patch(android_build_client, "AndroidBuildClient",
169                   return_value=build_client)
170        self.Patch(auth, "CreateCredentials", return_value=mock.MagicMock())
171        self.Patch(build_client, "GetBranch", return_value=expected_branch)
172        self.assertEqual(self.AvdSpec._GetBuildBranch(build_id, build_target),
173                         expected_branch)
174        # Infer branch from "repo info" when build_id and build_target is None.
175        self.Patch(self.AvdSpec, "_GetBranchFromRepo", return_value="repo_branch")
176        build_id = None
177        build_target = None
178        expected_branch = "repo_branch"
179        self.assertEqual(self.AvdSpec._GetBuildBranch(build_id, build_target),
180                         expected_branch)
181
182    # pylint: disable=protected-access
183    def testGetBuildTarget(self):
184        """Test get build target name."""
185        self.AvdSpec._remote_image[constants.BUILD_BRANCH] = "git_branch"
186        self.AvdSpec._flavor = constants.FLAVOR_IOT
187        self.args.avd_type = constants.TYPE_GCE
188        self.assertEqual(
189            self.AvdSpec._GetBuildTarget(self.args),
190            "gce_x86_iot-userdebug")
191
192        self.AvdSpec._remote_image[constants.BUILD_BRANCH] = "aosp-master"
193        self.AvdSpec._flavor = constants.FLAVOR_PHONE
194        self.args.avd_type = constants.TYPE_CF
195        self.assertEqual(
196            self.AvdSpec._GetBuildTarget(self.args),
197            "aosp_cf_x86_phone-userdebug")
198
199        self.AvdSpec._remote_image[constants.BUILD_BRANCH] = "git_branch"
200        self.AvdSpec._flavor = constants.FLAVOR_PHONE
201        self.args.avd_type = constants.TYPE_CF
202        self.assertEqual(
203            self.AvdSpec._GetBuildTarget(self.args),
204            "cf_x86_phone-userdebug")
205
206    # pylint: disable=protected-access
207    def testProcessHWPropertyWithInvalidArgs(self):
208        """Test _ProcessHWPropertyArgs with invalid args."""
209        # Checking wrong resolution.
210        args = mock.MagicMock()
211        args.hw_property = "cpu:3,resolution:1280"
212        args.reuse_instance_name = None
213        with self.assertRaises(errors.InvalidHWPropertyError):
214            self.AvdSpec._ProcessHWPropertyArgs(args)
215
216        # Checking property should be int.
217        args = mock.MagicMock()
218        args.hw_property = "cpu:3,dpi:fake"
219        with self.assertRaises(errors.InvalidHWPropertyError):
220            self.AvdSpec._ProcessHWPropertyArgs(args)
221
222        # Checking disk property should be with 'g' suffix.
223        args = mock.MagicMock()
224        args.hw_property = "cpu:3,disk:2"
225        with self.assertRaises(errors.InvalidHWPropertyError):
226            self.AvdSpec._ProcessHWPropertyArgs(args)
227
228        # Checking memory property should be with 'g' suffix.
229        args = mock.MagicMock()
230        args.hw_property = "cpu:3,memory:2"
231        with self.assertRaises(errors.InvalidHWPropertyError):
232            self.AvdSpec._ProcessHWPropertyArgs(args)
233
234    # pylint: disable=protected-access
235    def testParseHWPropertyStr(self):
236        """Test _ParseHWPropertyStr."""
237        expected_dict = {"cpu": "2", "x_res": "1080", "y_res": "1920",
238                         "dpi": "240", "memory": "4096", "disk": "4096"}
239        args_str = "cpu:2,resolution:1080x1920,dpi:240,memory:4g,disk:4g"
240        result_dict = self.AvdSpec._ParseHWPropertyStr(args_str)
241        self.assertTrue(expected_dict == result_dict)
242
243        expected_dict = {"cpu": "2", "x_res": "1080", "y_res": "1920",
244                         "dpi": "240", "memory": "512", "disk": "4096"}
245        args_str = "cpu:2,resolution:1080x1920,dpi:240,memory:512m,disk:4g"
246        result_dict = self.AvdSpec._ParseHWPropertyStr(args_str)
247        self.assertTrue(expected_dict == result_dict)
248
249    def testGetFlavorFromBuildTargetString(self):
250        """Test _GetFlavorFromLocalImage."""
251        img_path = "/fack_path/cf_x86_tv-img-eng.user.zip"
252        self.assertEqual(self.AvdSpec._GetFlavorFromString(img_path),
253                         "tv")
254
255        build_target_str = "aosp_cf_x86_auto"
256        self.assertEqual(self.AvdSpec._GetFlavorFromString(
257            build_target_str), "auto")
258
259        # Flavor is not supported.
260        img_path = "/fack_path/cf_x86_error-img-eng.user.zip"
261        self.assertEqual(self.AvdSpec._GetFlavorFromString(img_path),
262                         None)
263
264    # pylint: disable=protected-access
265    def testProcessRemoteBuildArgs(self):
266        """Test _ProcessRemoteBuildArgs."""
267        self.args.branch = "git_master"
268        self.args.build_id = "1234"
269
270        # Verify auto-assigned avd_type if build_targe contains "_gce_".
271        self.args.build_target = "aosp_gce_x86_phone-userdebug"
272        self.AvdSpec._ProcessRemoteBuildArgs(self.args)
273        self.assertTrue(self.AvdSpec.avd_type == "gce")
274
275        # Verify auto-assigned avd_type if build_targe contains "gce_".
276        self.args.build_target = "gce_x86_phone-userdebug"
277        self.AvdSpec._ProcessRemoteBuildArgs(self.args)
278        self.assertTrue(self.AvdSpec.avd_type == "gce")
279
280        # Verify auto-assigned avd_type if build_targe contains "_cf_".
281        self.args.build_target = "aosp_cf_x86_phone-userdebug"
282        self.AvdSpec._ProcessRemoteBuildArgs(self.args)
283        self.assertTrue(self.AvdSpec.avd_type == "cuttlefish")
284
285        # Verify auto-assigned avd_type if build_targe contains "cf_".
286        self.args.build_target = "cf_x86_phone-userdebug"
287        self.AvdSpec._ProcessRemoteBuildArgs(self.args)
288        self.assertTrue(self.AvdSpec.avd_type == "cuttlefish")
289
290        # Verify auto-assigned avd_type if build_targe contains "sdk_".
291        self.args.build_target = "sdk_phone_armv7-sdk"
292        self.AvdSpec._ProcessRemoteBuildArgs(self.args)
293        self.assertTrue(self.AvdSpec.avd_type == "goldfish")
294
295        # Verify auto-assigned avd_type if build_targe contains "_sdk_".
296        self.args.build_target = "aosp_sdk_phone_armv7-sdk"
297        self.AvdSpec._ProcessRemoteBuildArgs(self.args)
298        self.assertTrue(self.AvdSpec.avd_type == "goldfish")
299
300        # Verify auto-assigned avd_type if no match, default as cuttlefish.
301        self.args.build_target = "mini_emulator_arm64-userdebug"
302        self.args.avd_type = "cuttlefish"
303        # reset args.avd_type default value as cuttlefish.
304        self.AvdSpec = avd_spec.AVDSpec(self.args)
305        self.AvdSpec._ProcessRemoteBuildArgs(self.args)
306        self.assertTrue(self.AvdSpec.avd_type == "cuttlefish")
307
308    def testEscapeAnsi(self):
309        """Test EscapeAnsi."""
310        test_string = "\033[1;32;40m Manifest branch:"
311        expected_result = " Manifest branch:"
312        self.assertEqual(avd_spec.EscapeAnsi(test_string), expected_result)
313
314    def testGetGceLocalImagePath(self):
315        """Test get gce local image path."""
316        self.Patch(os.path, "isfile", return_value=True)
317        # Verify when specify --local-image ~/XXX.tar.gz.
318        fake_image_path = "~/gce_local_image_dir/gce_image.tar.gz"
319        self.Patch(os.path, "exists", return_value=True)
320        self.assertEqual(self.AvdSpec._GetGceLocalImagePath(fake_image_path),
321                         "~/gce_local_image_dir/gce_image.tar.gz")
322
323        # Verify when specify --local-image ~/XXX.img.
324        fake_image_path = "~/gce_local_image_dir/gce_image.img"
325        self.assertEqual(self.AvdSpec._GetGceLocalImagePath(fake_image_path),
326                         "~/gce_local_image_dir/gce_image.img")
327
328        # Verify if exist argument --local-image as a directory.
329        self.Patch(os.path, "isfile", return_value=False)
330        self.Patch(os.path, "exists", return_value=True)
331        fake_image_path = "~/gce_local_image_dir/"
332        # Default to find */avd-system.tar.gz if exist then return the path.
333        self.assertEqual(self.AvdSpec._GetGceLocalImagePath(fake_image_path),
334                         "~/gce_local_image_dir/avd-system.tar.gz")
335
336        # Otherwise choose raw file */android_system_disk_syslinux.img if
337        # exist then return the path.
338        self.Patch(os.path, "exists", side_effect=[False, True])
339        self.assertEqual(self.AvdSpec._GetGceLocalImagePath(fake_image_path),
340                         "~/gce_local_image_dir/android_system_disk_syslinux.img")
341
342        # Both _GCE_LOCAL_IMAGE_CANDIDATE could not be found then raise error.
343        self.Patch(os.path, "exists", side_effect=[False, False])
344        self.assertRaises(errors.ImgDoesNotExist,
345                          self.AvdSpec._GetGceLocalImagePath, fake_image_path)
346
347    def testProcessMiscArgs(self):
348        """Test process misc args."""
349        self.args.remote_host = None
350        self.args.local_instance = None
351        self.AvdSpec._ProcessMiscArgs(self.args)
352        self.assertEqual(self.AvdSpec._instance_type, constants.INSTANCE_TYPE_REMOTE)
353
354        self.args.remote_host = None
355        self.args.local_instance = True
356        self.AvdSpec._ProcessMiscArgs(self.args)
357        self.assertEqual(self.AvdSpec._instance_type, constants.INSTANCE_TYPE_LOCAL)
358
359        self.args.remote_host = "1.1.1.1"
360        self.args.local_instance = None
361        self.AvdSpec._ProcessMiscArgs(self.args)
362        self.assertEqual(self.AvdSpec._instance_type, constants.INSTANCE_TYPE_HOST)
363
364        self.args.remote_host = "1.1.1.1"
365        self.args.local_instance = True
366        self.AvdSpec._ProcessMiscArgs(self.args)
367        self.assertEqual(self.AvdSpec._instance_type, constants.INSTANCE_TYPE_HOST)
368
369        # Test avd_spec.autoconnect
370        self.args.autoconnect = False
371        self.AvdSpec._ProcessMiscArgs(self.args)
372        self.assertEqual(self.AvdSpec.autoconnect, False)
373        self.assertEqual(self.AvdSpec.connect_adb, False)
374        self.assertEqual(self.AvdSpec.connect_vnc, False)
375        self.assertEqual(self.AvdSpec.connect_webrtc, False)
376
377        self.args.autoconnect = constants.INS_KEY_VNC
378        self.AvdSpec._ProcessMiscArgs(self.args)
379        self.assertEqual(self.AvdSpec.autoconnect, True)
380        self.assertEqual(self.AvdSpec.connect_adb, True)
381        self.assertEqual(self.AvdSpec.connect_vnc, True)
382        self.assertEqual(self.AvdSpec.connect_webrtc, False)
383
384        self.args.autoconnect = constants.INS_KEY_ADB
385        self.AvdSpec._ProcessMiscArgs(self.args)
386        self.assertEqual(self.AvdSpec.autoconnect, True)
387        self.assertEqual(self.AvdSpec.connect_adb, True)
388        self.assertEqual(self.AvdSpec.connect_vnc, False)
389        self.assertEqual(self.AvdSpec.connect_webrtc, False)
390
391        self.args.autoconnect = constants.INS_KEY_WEBRTC
392        self.AvdSpec._ProcessMiscArgs(self.args)
393        self.assertEqual(self.AvdSpec.autoconnect, True)
394        self.assertEqual(self.AvdSpec.connect_adb, True)
395        self.assertEqual(self.AvdSpec.connect_vnc, False)
396        self.assertEqual(self.AvdSpec.connect_webrtc, True)
397
398
399if __name__ == "__main__":
400    unittest.main()
401