xref: /aosp_15_r20/tools/acloud/internal/lib/goldfish_utils_test.py (revision 800a58d989c669b8eb8a71d8df53b1ba3d411444)
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