1#!/usr/bin/env python3 2# 3# Copyright 2021 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17"""Unit tests for goldfish_utils.""" 18 19import os 20import shutil 21import tempfile 22import unittest 23 24from unittest import mock 25 26from acloud import errors 27from acloud.internal.lib import goldfish_utils 28 29 30class GoldfishUtilsTest(unittest.TestCase): 31 """Test functions in goldfish_utils.""" 32 33 # Remote host instance name. 34 _IP_ADDRESS = "192.0.2.1" 35 _DOMAIN_NAME = "host.NAME-1234" 36 _CONSOLE_PORT = 5554 37 _BUILD_INFO = {"build_id": "123456", 38 "build_target": "sdk_phone_x86_64-userdebug"} 39 _INSTANCE_NAME_WITH_IP = ("host-goldfish-192.0.2.1-5554-" 40 "123456-sdk_phone_x86_64-userdebug") 41 _INSTANCE_NAME_WITH_DOMAIN = ("host-goldfish-host.NAME_1234-5554-" 42 "123456-sdk_phone_x86_64-userdebug") 43 _INSTANCE_NAME_WITHOUT_INFO = "host-goldfish-192.0.2.1-5554-userbuild" 44 _INVALID_NAME = "host-192.0.2.1-123456-aosp_cf_x86_phone-userdebug" 45 46 @staticmethod 47 def _CreateEmptyFile(path): 48 os.makedirs(os.path.dirname(path), exist_ok=True) 49 with open(path, "w"): 50 pass 51 52 def setUp(self): 53 """Create the temporary directory.""" 54 self._temp_dir = tempfile.mkdtemp("goldfish_utils_test") 55 56 def tearDown(self): 57 """Delete the temporary directory.""" 58 shutil.rmtree(self._temp_dir) 59 60 def testMixWithBootImage(self): 61 """Test MixWithBootImage.""" 62 boot_image_path = os.path.join(self._temp_dir, "boot.img") 63 image_dir = os.path.join(self._temp_dir, "image_dir") 64 self._CreateEmptyFile(boot_image_path) 65 os.makedirs(image_dir) 66 with open(os.path.join(image_dir, "ramdisk-qemu.img"), "w") as ramdisk: 67 ramdisk.write("original") 68 mix_dir = os.path.join(self._temp_dir, "mix_kernel") 69 unpack_dir = os.path.join(mix_dir, "unpacked_boot_img") 70 71 def _MockUnpackBootImg(out_dir, boot_img): 72 self.assertEqual(unpack_dir, out_dir) 73 self.assertEqual(boot_image_path, boot_img) 74 self._CreateEmptyFile(os.path.join(out_dir, "kernel")) 75 with open(os.path.join(out_dir, "ramdisk"), "w") as ramdisk: 76 ramdisk.write("boot") 77 78 mock_ota = mock.Mock() 79 mock_ota.UnpackBootImg.side_effect = _MockUnpackBootImg 80 81 kernel_path, ramdisk_path = goldfish_utils.MixWithBootImage( 82 mix_dir, image_dir, boot_image_path, mock_ota) 83 84 mock_ota.UnpackBootImg.assert_called_with(unpack_dir, boot_image_path) 85 self.assertEqual(os.path.join(unpack_dir, "kernel"), kernel_path) 86 self.assertEqual(os.path.join(mix_dir, "mixed_ramdisk"), ramdisk_path) 87 with open(ramdisk_path, "r") as ramdisk: 88 self.assertEqual("originalboot", ramdisk.read()) 89 90 def testFindKernelImage(self): 91 """Test FindKernelImage.""" 92 with self.assertRaises(errors.GetLocalImageError): 93 goldfish_utils.FindKernelImages(self._temp_dir) 94 95 kernel_path = os.path.join(self._temp_dir, "kernel") 96 ramdisk_path = os.path.join(self._temp_dir, "ramdisk.img") 97 self._CreateEmptyFile(kernel_path) 98 self._CreateEmptyFile(ramdisk_path) 99 self.assertEqual((kernel_path, ramdisk_path), 100 goldfish_utils.FindKernelImages(self._temp_dir)) 101 102 kernel_path = os.path.join(self._temp_dir, "kernel-ranchu") 103 ramdisk_path = os.path.join(self._temp_dir, "ramdisk-qemu.img") 104 self._CreateEmptyFile(kernel_path) 105 self._CreateEmptyFile(ramdisk_path) 106 self.assertEqual((kernel_path, ramdisk_path), 107 goldfish_utils.FindKernelImages(self._temp_dir)) 108 109 def testFindSystemDlkmImage(self): 110 """Test FindSystemDlkmImage.""" 111 system_dlkm_image_path = os.path.join(self._temp_dir, "test.img") 112 self._CreateEmptyFile(system_dlkm_image_path) 113 self.assertEqual( 114 system_dlkm_image_path, 115 goldfish_utils.FindSystemDlkmImage(system_dlkm_image_path)) 116 117 with self.assertRaises(errors.GetLocalImageError): 118 goldfish_utils.FindSystemDlkmImage(self._temp_dir) 119 120 system_dlkm_image_path = os.path.join(self._temp_dir, 121 "system_dlkm.img") 122 self._CreateEmptyFile(system_dlkm_image_path) 123 self.assertEqual(system_dlkm_image_path, 124 goldfish_utils.FindSystemDlkmImage(self._temp_dir)) 125 126 system_dlkm_image_path = os.path.join(self._temp_dir, 127 "system_dlkm.flatten.ext4.img") 128 self._CreateEmptyFile(system_dlkm_image_path) 129 self.assertEqual(system_dlkm_image_path, 130 goldfish_utils.FindSystemDlkmImage(self._temp_dir)) 131 132 def testFindDiskImage(self): 133 """Test FindDiskImage.""" 134 with self.assertRaises(errors.GetLocalImageError): 135 goldfish_utils.FindDiskImage(self._temp_dir) 136 137 disk_path = os.path.join(self._temp_dir, "system.img") 138 self._CreateEmptyFile(disk_path) 139 self.assertEqual(disk_path, 140 goldfish_utils.FindDiskImage(self._temp_dir)) 141 142 disk_path = os.path.join(self._temp_dir, "system-qemu.img") 143 self._CreateEmptyFile(disk_path) 144 self.assertEqual(disk_path, 145 goldfish_utils.FindDiskImage(self._temp_dir)) 146 147 def testMixDiskImage(self): 148 """Test MixDiskImage.""" 149 mock_ota = mock.Mock() 150 mix_dir = os.path.join(self._temp_dir, "mix_disk") 151 image_dir = os.path.join(self._temp_dir, "image_dir") 152 misc_info_path = os.path.join(image_dir, "misc_info.txt") 153 qemu_config_path = os.path.join(image_dir, "system-qemu-config.txt") 154 system_image_path = os.path.join(self._temp_dir, "system.img") 155 system_dlkm_image_path = os.path.join(self._temp_dir, 156 "system_dlkm.img") 157 vendor_image_path = os.path.join(image_dir, "vendor.img") 158 vbmeta_image_path = os.path.join(mix_dir, "disabled_vbmeta.img") 159 super_image_path = os.path.join(mix_dir, "mixed_super.img") 160 self._CreateEmptyFile(misc_info_path) 161 self._CreateEmptyFile(qemu_config_path) 162 163 disk_image = goldfish_utils.MixDiskImage( 164 mix_dir, image_dir, system_image_path, system_dlkm_image_path, 165 mock_ota) 166 167 self.assertTrue(os.path.isdir(mix_dir)) 168 self.assertEqual(os.path.join(mix_dir, "mixed_disk.img"), disk_image) 169 170 mock_ota.BuildSuperImage.assert_called_with( 171 os.path.join(mix_dir, "mixed_super.img"), misc_info_path, mock.ANY) 172 get_image = mock_ota.BuildSuperImage.call_args[0][2] 173 self._CreateEmptyFile(vendor_image_path) 174 self._CreateEmptyFile(system_image_path) 175 self._CreateEmptyFile(system_dlkm_image_path) 176 self.assertEqual(system_image_path, get_image("system")) 177 self.assertEqual(system_dlkm_image_path, get_image("system_dlkm")) 178 self.assertEqual(vendor_image_path, get_image("vendor")) 179 180 mock_ota.MakeDisabledVbmetaImage.assert_called_with(vbmeta_image_path) 181 182 mock_ota.MkCombinedImg.assert_called_with( 183 disk_image, qemu_config_path, mock.ANY) 184 get_image = mock_ota.MkCombinedImg.call_args[0][2] 185 self._CreateEmptyFile(vbmeta_image_path) 186 self._CreateEmptyFile(super_image_path) 187 self.assertEqual(vbmeta_image_path, get_image("vbmeta")) 188 self.assertEqual(super_image_path, get_image("super")) 189 190 def testParseRemoteHostConsoleAddress(self): 191 """Test ParseRemoteHostConsoleAddress.""" 192 console_addr = goldfish_utils.ParseRemoteHostConsoleAddress( 193 self._INSTANCE_NAME_WITH_IP) 194 self.assertEqual((self._IP_ADDRESS, self._CONSOLE_PORT), console_addr) 195 196 console_addr = goldfish_utils.ParseRemoteHostConsoleAddress( 197 self._INSTANCE_NAME_WITH_DOMAIN) 198 self.assertEqual((self._DOMAIN_NAME, self._CONSOLE_PORT), console_addr) 199 200 console_addr = goldfish_utils.ParseRemoteHostConsoleAddress( 201 self._INVALID_NAME) 202 self.assertIsNone(console_addr) 203 204 def testFormatInstanceName(self): 205 """Test FormatRemoteHostInstanceName.""" 206 instance_name = goldfish_utils.FormatRemoteHostInstanceName( 207 self._IP_ADDRESS, self._CONSOLE_PORT, self._BUILD_INFO) 208 self.assertEqual(self._INSTANCE_NAME_WITH_IP, instance_name) 209 210 instance_name = goldfish_utils.FormatRemoteHostInstanceName( 211 self._DOMAIN_NAME, self._CONSOLE_PORT, self._BUILD_INFO) 212 self.assertEqual(self._INSTANCE_NAME_WITH_DOMAIN, instance_name) 213 214 instance_name = goldfish_utils.FormatRemoteHostInstanceName( 215 self._IP_ADDRESS, self._CONSOLE_PORT, {}) 216 self.assertEqual(self._INSTANCE_NAME_WITHOUT_INFO, instance_name) 217 218 def testConvertAvdSpecToArgs(self): 219 """Test ConvertAvdSpecToArgs.""" 220 hw_property = { 221 "cpu": "2", 222 "x_res": "1270", 223 "y_res": "700", 224 "memory": "2048", 225 "disk": "4096" 226 } 227 mock_spec = mock.Mock(hw_customize=True, gpu='off', 228 hw_property=hw_property) 229 self.assertEqual(["-gpu", "off", "-cores", "2", "-skin", "1270x700", 230 "-memory", "2048", "-partition-size", "4096"], 231 goldfish_utils.ConvertAvdSpecToArgs(mock_spec)) 232 233 mock_spec = mock.Mock(hw_customize=True, gpu=None, hw_property={}) 234 self.assertEqual([], goldfish_utils.ConvertAvdSpecToArgs(mock_spec)) 235 236 237if __name__ == "__main__": 238 unittest.main() 239