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 testFindDiskImage(self): 107 """Test FindDiskImage.""" 108 with self.assertRaises(errors.GetLocalImageError): 109 goldfish_utils.FindDiskImage(self._temp_dir) 110 111 disk_path = os.path.join(self._temp_dir, "system.img") 112 self._CreateEmptyFile(disk_path) 113 self.assertEqual(disk_path, 114 goldfish_utils.FindDiskImage(self._temp_dir)) 115 116 disk_path = os.path.join(self._temp_dir, "system-qemu.img") 117 self._CreateEmptyFile(disk_path) 118 self.assertEqual(disk_path, 119 goldfish_utils.FindDiskImage(self._temp_dir)) 120 121 def testMixWithSystemImage(self): 122 """Test MixWithSystemImage.""" 123 mock_ota = mock.Mock() 124 mix_dir = os.path.join(self._temp_dir, "mix_disk") 125 image_dir = os.path.join(self._temp_dir, "image_dir") 126 misc_info_path = os.path.join(image_dir, "misc_info.txt") 127 qemu_config_path = os.path.join(image_dir, "system-qemu-config.txt") 128 system_image_path = os.path.join(self._temp_dir, "system.img") 129 vendor_image_path = os.path.join(image_dir, "vendor.img") 130 vbmeta_image_path = os.path.join(mix_dir, "disabled_vbmeta.img") 131 super_image_path = os.path.join(mix_dir, "mixed_super.img") 132 self._CreateEmptyFile(misc_info_path) 133 self._CreateEmptyFile(qemu_config_path) 134 135 disk_image = goldfish_utils.MixWithSystemImage( 136 mix_dir, image_dir, system_image_path, mock_ota) 137 138 self.assertTrue(os.path.isdir(mix_dir)) 139 self.assertEqual(os.path.join(mix_dir, "mixed_disk.img"), disk_image) 140 141 mock_ota.BuildSuperImage.assert_called_with( 142 os.path.join(mix_dir, "mixed_super.img"), misc_info_path, mock.ANY) 143 get_image = mock_ota.BuildSuperImage.call_args[0][2] 144 self._CreateEmptyFile(vendor_image_path) 145 self._CreateEmptyFile(system_image_path) 146 self.assertEqual(system_image_path, get_image("system")) 147 self.assertEqual(vendor_image_path, get_image("vendor")) 148 149 mock_ota.MakeDisabledVbmetaImage.assert_called_with(vbmeta_image_path) 150 151 mock_ota.MkCombinedImg.assert_called_with( 152 disk_image, qemu_config_path, mock.ANY) 153 get_image = mock_ota.MkCombinedImg.call_args[0][2] 154 self._CreateEmptyFile(vbmeta_image_path) 155 self._CreateEmptyFile(super_image_path) 156 self.assertEqual(vbmeta_image_path, get_image("vbmeta")) 157 self.assertEqual(super_image_path, get_image("super")) 158 159 def testParseRemoteHostConsoleAddress(self): 160 """Test ParseRemoteHostConsoleAddress.""" 161 console_addr = goldfish_utils.ParseRemoteHostConsoleAddress( 162 self._INSTANCE_NAME) 163 self.assertEqual((self._IP_ADDRESS, self._CONSOLE_PORT), console_addr) 164 165 console_addr = goldfish_utils.ParseRemoteHostConsoleAddress( 166 self._INVALID_NAME) 167 self.assertIsNone(console_addr) 168 169 def testFormatInstanceName(self): 170 """Test FormatRemoteHostInstanceName.""" 171 instance_name = goldfish_utils.FormatRemoteHostInstanceName( 172 self._IP_ADDRESS, self._CONSOLE_PORT, self._BUILD_INFO) 173 self.assertEqual(self._INSTANCE_NAME, instance_name) 174 175 instance_name = goldfish_utils.FormatRemoteHostInstanceName( 176 self._IP_ADDRESS, self._CONSOLE_PORT, {}) 177 self.assertEqual(self._INSTANCE_NAME_WITHOUT_INFO, instance_name) 178 179 def testConvertAvdSpecToArgs(self): 180 """Test ConvertAvdSpecToArgs.""" 181 hw_property = { 182 "cpu": "2", 183 "x_res": "1270", 184 "y_res": "700", 185 "memory": "2048", 186 "disk": "4096" 187 } 188 mock_spec = mock.Mock(hw_customize=True, gpu='off', 189 hw_property=hw_property) 190 self.assertEqual(["-gpu", "off", "-cores", "2", "-skin", "1270x700", 191 "-memory", "2048", "-partition-size", "4096"], 192 goldfish_utils.ConvertAvdSpecToArgs(mock_spec)) 193 194 mock_spec = mock.Mock(hw_customize=True, gpu=None, hw_property={}) 195 self.assertEqual([], goldfish_utils.ConvertAvdSpecToArgs(mock_spec)) 196 197 198if __name__ == "__main__": 199 unittest.main() 200