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 _CONSOLE_PORT = 5554 36 _BUILD_INFO = {"build_id": "123456", 37 "build_target": "sdk_phone_x86_64-userdebug"} 38 _INSTANCE_NAME = ("host-goldfish-192.0.2.1-5554-" 39 "123456-sdk_phone_x86_64-userdebug") 40 _INSTANCE_NAME_WITHOUT_INFO = "host-goldfish-192.0.2.1-5554-userbuild" 41 _INVALID_NAME = "host-192.0.2.1-123456-aosp_cf_x86_phone-userdebug" 42 43 @staticmethod 44 def _CreateEmptyFile(path): 45 os.makedirs(os.path.dirname(path), exist_ok=True) 46 with open(path, "w"): 47 pass 48 49 def setUp(self): 50 """Create the temporary directory.""" 51 self._temp_dir = tempfile.mkdtemp("goldfish_utils_test") 52 53 def tearDown(self): 54 """Delete the temporary directory.""" 55 shutil.rmtree(self._temp_dir) 56 57 def testMixWithBootImage(self): 58 """Test MixWithBootImage.""" 59 boot_image_path = os.path.join(self._temp_dir, "boot.img") 60 image_dir = os.path.join(self._temp_dir, "image_dir") 61 self._CreateEmptyFile(boot_image_path) 62 os.makedirs(image_dir) 63 with open(os.path.join(image_dir, "ramdisk-qemu.img"), "w") as ramdisk: 64 ramdisk.write("original") 65 mix_dir = os.path.join(self._temp_dir, "mix_kernel") 66 unpack_dir = os.path.join(mix_dir, "unpacked_boot_img") 67 68 def _MockUnpackBootImg(out_dir, boot_img): 69 self.assertEqual(unpack_dir, out_dir) 70 self.assertEqual(boot_image_path, boot_img) 71 self._CreateEmptyFile(os.path.join(out_dir, "kernel")) 72 with open(os.path.join(out_dir, "ramdisk"), "w") as ramdisk: 73 ramdisk.write("boot") 74 75 mock_ota = mock.Mock() 76 mock_ota.UnpackBootImg.side_effect = _MockUnpackBootImg 77 78 kernel_path, ramdisk_path = goldfish_utils.MixWithBootImage( 79 mix_dir, image_dir, boot_image_path, mock_ota) 80 81 mock_ota.UnpackBootImg.assert_called_with(unpack_dir, boot_image_path) 82 self.assertEqual(os.path.join(unpack_dir, "kernel"), kernel_path) 83 self.assertEqual(os.path.join(mix_dir, "mixed_ramdisk"), ramdisk_path) 84 with open(ramdisk_path, "r") as ramdisk: 85 self.assertEqual("originalboot", ramdisk.read()) 86 87 def testFindKernelImage(self): 88 """Test FindKernelImage.""" 89 with self.assertRaises(errors.GetLocalImageError): 90 goldfish_utils.FindKernelImages(self._temp_dir) 91 92 kernel_path = os.path.join(self._temp_dir, "kernel") 93 ramdisk_path = os.path.join(self._temp_dir, "ramdisk.img") 94 self._CreateEmptyFile(kernel_path) 95 self._CreateEmptyFile(ramdisk_path) 96 self.assertEqual((kernel_path, ramdisk_path), 97 goldfish_utils.FindKernelImages(self._temp_dir)) 98 99 kernel_path = os.path.join(self._temp_dir, "kernel-ranchu") 100 ramdisk_path = os.path.join(self._temp_dir, "ramdisk-qemu.img") 101 self._CreateEmptyFile(kernel_path) 102 self._CreateEmptyFile(ramdisk_path) 103 self.assertEqual((kernel_path, ramdisk_path), 104 goldfish_utils.FindKernelImages(self._temp_dir)) 105 106 def testFindSystemDlkmImage(self): 107 """Test FindSystemDlkmImage.""" 108 system_dlkm_image_path = os.path.join(self._temp_dir, "test.img") 109 self._CreateEmptyFile(system_dlkm_image_path) 110 self.assertEqual( 111 system_dlkm_image_path, 112 goldfish_utils.FindSystemDlkmImage(system_dlkm_image_path)) 113 114 with self.assertRaises(errors.GetLocalImageError): 115 goldfish_utils.FindSystemDlkmImage(self._temp_dir) 116 117 system_dlkm_image_path = os.path.join(self._temp_dir, 118 "system_dlkm.img") 119 self._CreateEmptyFile(system_dlkm_image_path) 120 self.assertEqual(system_dlkm_image_path, 121 goldfish_utils.FindSystemDlkmImage(self._temp_dir)) 122 123 system_dlkm_image_path = os.path.join(self._temp_dir, 124 "system_dlkm.flatten.ext4.img") 125 self._CreateEmptyFile(system_dlkm_image_path) 126 self.assertEqual(system_dlkm_image_path, 127 goldfish_utils.FindSystemDlkmImage(self._temp_dir)) 128 129 def testFindDiskImage(self): 130 """Test FindDiskImage.""" 131 with self.assertRaises(errors.GetLocalImageError): 132 goldfish_utils.FindDiskImage(self._temp_dir) 133 134 disk_path = os.path.join(self._temp_dir, "system.img") 135 self._CreateEmptyFile(disk_path) 136 self.assertEqual(disk_path, 137 goldfish_utils.FindDiskImage(self._temp_dir)) 138 139 disk_path = os.path.join(self._temp_dir, "system-qemu.img") 140 self._CreateEmptyFile(disk_path) 141 self.assertEqual(disk_path, 142 goldfish_utils.FindDiskImage(self._temp_dir)) 143 144 def testMixDiskImage(self): 145 """Test MixDiskImage.""" 146 mock_ota = mock.Mock() 147 mix_dir = os.path.join(self._temp_dir, "mix_disk") 148 image_dir = os.path.join(self._temp_dir, "image_dir") 149 misc_info_path = os.path.join(image_dir, "misc_info.txt") 150 qemu_config_path = os.path.join(image_dir, "system-qemu-config.txt") 151 system_image_path = os.path.join(self._temp_dir, "system.img") 152 system_dlkm_image_path = os.path.join(self._temp_dir, 153 "system_dlkm.img") 154 vendor_image_path = os.path.join(image_dir, "vendor.img") 155 vbmeta_image_path = os.path.join(mix_dir, "disabled_vbmeta.img") 156 super_image_path = os.path.join(mix_dir, "mixed_super.img") 157 self._CreateEmptyFile(misc_info_path) 158 self._CreateEmptyFile(qemu_config_path) 159 160 disk_image = goldfish_utils.MixDiskImage( 161 mix_dir, image_dir, system_image_path, system_dlkm_image_path, 162 mock_ota) 163 164 self.assertTrue(os.path.isdir(mix_dir)) 165 self.assertEqual(os.path.join(mix_dir, "mixed_disk.img"), disk_image) 166 167 mock_ota.BuildSuperImage.assert_called_with( 168 os.path.join(mix_dir, "mixed_super.img"), misc_info_path, mock.ANY) 169 get_image = mock_ota.BuildSuperImage.call_args[0][2] 170 self._CreateEmptyFile(vendor_image_path) 171 self._CreateEmptyFile(system_image_path) 172 self._CreateEmptyFile(system_dlkm_image_path) 173 self.assertEqual(system_image_path, get_image("system")) 174 self.assertEqual(system_dlkm_image_path, get_image("system_dlkm")) 175 self.assertEqual(vendor_image_path, get_image("vendor")) 176 177 mock_ota.MakeDisabledVbmetaImage.assert_called_with(vbmeta_image_path) 178 179 mock_ota.MkCombinedImg.assert_called_with( 180 disk_image, qemu_config_path, mock.ANY) 181 get_image = mock_ota.MkCombinedImg.call_args[0][2] 182 self._CreateEmptyFile(vbmeta_image_path) 183 self._CreateEmptyFile(super_image_path) 184 self.assertEqual(vbmeta_image_path, get_image("vbmeta")) 185 self.assertEqual(super_image_path, get_image("super")) 186 187 def testParseRemoteHostConsoleAddress(self): 188 """Test ParseRemoteHostConsoleAddress.""" 189 console_addr = goldfish_utils.ParseRemoteHostConsoleAddress( 190 self._INSTANCE_NAME) 191 self.assertEqual((self._IP_ADDRESS, self._CONSOLE_PORT), console_addr) 192 193 console_addr = goldfish_utils.ParseRemoteHostConsoleAddress( 194 self._INVALID_NAME) 195 self.assertIsNone(console_addr) 196 197 def testFormatInstanceName(self): 198 """Test FormatRemoteHostInstanceName.""" 199 instance_name = goldfish_utils.FormatRemoteHostInstanceName( 200 self._IP_ADDRESS, self._CONSOLE_PORT, self._BUILD_INFO) 201 self.assertEqual(self._INSTANCE_NAME, instance_name) 202 203 instance_name = goldfish_utils.FormatRemoteHostInstanceName( 204 self._IP_ADDRESS, self._CONSOLE_PORT, {}) 205 self.assertEqual(self._INSTANCE_NAME_WITHOUT_INFO, instance_name) 206 207 def testConvertAvdSpecToArgs(self): 208 """Test ConvertAvdSpecToArgs.""" 209 hw_property = { 210 "cpu": "2", 211 "x_res": "1270", 212 "y_res": "700", 213 "memory": "2048", 214 "disk": "4096" 215 } 216 mock_spec = mock.Mock(hw_customize=True, gpu='off', 217 hw_property=hw_property) 218 self.assertEqual(["-gpu", "off", "-cores", "2", "-skin", "1270x700", 219 "-memory", "2048", "-partition-size", "4096"], 220 goldfish_utils.ConvertAvdSpecToArgs(mock_spec)) 221 222 mock_spec = mock.Mock(hw_customize=True, gpu=None, hw_property={}) 223 self.assertEqual([], goldfish_utils.ConvertAvdSpecToArgs(mock_spec)) 224 225 226if __name__ == "__main__": 227 unittest.main() 228