xref: /aosp_15_r20/build/make/tools/releasetools/test_build_image.py (revision 9e94795a3d4ef5c1d47486f9a02bb378756cea8a)
1*9e94795aSAndroid Build Coastguard Worker#
2*9e94795aSAndroid Build Coastguard Worker# Copyright (C) 2017 The Android Open Source Project
3*9e94795aSAndroid Build Coastguard Worker#
4*9e94795aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*9e94795aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*9e94795aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*9e94795aSAndroid Build Coastguard Worker#
8*9e94795aSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
9*9e94795aSAndroid Build Coastguard Worker#
10*9e94795aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*9e94795aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
12*9e94795aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*9e94795aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*9e94795aSAndroid Build Coastguard Worker# limitations under the License.
15*9e94795aSAndroid Build Coastguard Worker#
16*9e94795aSAndroid Build Coastguard Worker
17*9e94795aSAndroid Build Coastguard Workerimport filecmp
18*9e94795aSAndroid Build Coastguard Workerimport os.path
19*9e94795aSAndroid Build Coastguard Worker
20*9e94795aSAndroid Build Coastguard Workerimport common
21*9e94795aSAndroid Build Coastguard Workerimport test_utils
22*9e94795aSAndroid Build Coastguard Workerfrom build_image import (
23*9e94795aSAndroid Build Coastguard Worker    BuildImageError, CheckHeadroom, GetFilesystemCharacteristics,
24*9e94795aSAndroid Build Coastguard Worker    SetUpInDirAndFsConfig)
25*9e94795aSAndroid Build Coastguard Worker
26*9e94795aSAndroid Build Coastguard Worker
27*9e94795aSAndroid Build Coastguard Workerclass BuildImageTest(test_utils.ReleaseToolsTestCase):
28*9e94795aSAndroid Build Coastguard Worker
29*9e94795aSAndroid Build Coastguard Worker  # Available: 1000 blocks.
30*9e94795aSAndroid Build Coastguard Worker  EXT4FS_OUTPUT = (
31*9e94795aSAndroid Build Coastguard Worker      "Created filesystem with 2777/129024 inodes and 515099/516099 blocks")
32*9e94795aSAndroid Build Coastguard Worker
33*9e94795aSAndroid Build Coastguard Worker  def test_CheckHeadroom_SizeUnderLimit(self):
34*9e94795aSAndroid Build Coastguard Worker    # Required headroom: 1000 blocks.
35*9e94795aSAndroid Build Coastguard Worker    prop_dict = {
36*9e94795aSAndroid Build Coastguard Worker        'fs_type' : 'ext4',
37*9e94795aSAndroid Build Coastguard Worker        'partition_headroom' : '4096000',
38*9e94795aSAndroid Build Coastguard Worker        'mount_point' : 'system',
39*9e94795aSAndroid Build Coastguard Worker    }
40*9e94795aSAndroid Build Coastguard Worker    CheckHeadroom(self.EXT4FS_OUTPUT, prop_dict)
41*9e94795aSAndroid Build Coastguard Worker
42*9e94795aSAndroid Build Coastguard Worker  def test_CheckHeadroom_InsufficientHeadroom(self):
43*9e94795aSAndroid Build Coastguard Worker    # Required headroom: 1001 blocks.
44*9e94795aSAndroid Build Coastguard Worker    prop_dict = {
45*9e94795aSAndroid Build Coastguard Worker        'fs_type' : 'ext4',
46*9e94795aSAndroid Build Coastguard Worker        'partition_headroom' : '4100096',
47*9e94795aSAndroid Build Coastguard Worker        'mount_point' : 'system',
48*9e94795aSAndroid Build Coastguard Worker    }
49*9e94795aSAndroid Build Coastguard Worker    self.assertRaises(
50*9e94795aSAndroid Build Coastguard Worker        BuildImageError, CheckHeadroom, self.EXT4FS_OUTPUT, prop_dict)
51*9e94795aSAndroid Build Coastguard Worker
52*9e94795aSAndroid Build Coastguard Worker  @test_utils.SkipIfExternalToolsUnavailable()
53*9e94795aSAndroid Build Coastguard Worker  def test_CheckHeadroom_WrongFsType(self):
54*9e94795aSAndroid Build Coastguard Worker    prop_dict = {
55*9e94795aSAndroid Build Coastguard Worker        'fs_type' : 'f2fs',
56*9e94795aSAndroid Build Coastguard Worker        'partition_headroom' : '4100096',
57*9e94795aSAndroid Build Coastguard Worker        'mount_point' : 'system',
58*9e94795aSAndroid Build Coastguard Worker    }
59*9e94795aSAndroid Build Coastguard Worker    self.assertRaises(
60*9e94795aSAndroid Build Coastguard Worker        AssertionError, CheckHeadroom, self.EXT4FS_OUTPUT, prop_dict)
61*9e94795aSAndroid Build Coastguard Worker
62*9e94795aSAndroid Build Coastguard Worker  def test_CheckHeadroom_MissingProperties(self):
63*9e94795aSAndroid Build Coastguard Worker    prop_dict = {
64*9e94795aSAndroid Build Coastguard Worker        'fs_type' : 'ext4',
65*9e94795aSAndroid Build Coastguard Worker        'partition_headroom' : '4100096',
66*9e94795aSAndroid Build Coastguard Worker    }
67*9e94795aSAndroid Build Coastguard Worker    self.assertRaises(
68*9e94795aSAndroid Build Coastguard Worker        AssertionError, CheckHeadroom, self.EXT4FS_OUTPUT, prop_dict)
69*9e94795aSAndroid Build Coastguard Worker
70*9e94795aSAndroid Build Coastguard Worker    prop_dict = {
71*9e94795aSAndroid Build Coastguard Worker        'fs_type' : 'ext4',
72*9e94795aSAndroid Build Coastguard Worker        'mount_point' : 'system',
73*9e94795aSAndroid Build Coastguard Worker    }
74*9e94795aSAndroid Build Coastguard Worker    self.assertRaises(
75*9e94795aSAndroid Build Coastguard Worker        AssertionError, CheckHeadroom, self.EXT4FS_OUTPUT, prop_dict)
76*9e94795aSAndroid Build Coastguard Worker
77*9e94795aSAndroid Build Coastguard Worker  @test_utils.SkipIfExternalToolsUnavailable()
78*9e94795aSAndroid Build Coastguard Worker  def test_CheckHeadroom_WithMke2fsOutput(self):
79*9e94795aSAndroid Build Coastguard Worker    """Tests the result parsing from actual call to mke2fs."""
80*9e94795aSAndroid Build Coastguard Worker    input_dir = common.MakeTempDir()
81*9e94795aSAndroid Build Coastguard Worker    output_image = common.MakeTempFile(suffix='.img')
82*9e94795aSAndroid Build Coastguard Worker    command = ['mkuserimg_mke2fs', input_dir, output_image, 'ext4',
83*9e94795aSAndroid Build Coastguard Worker               '/system', '409600', '-j', '0']
84*9e94795aSAndroid Build Coastguard Worker    proc = common.Run(command)
85*9e94795aSAndroid Build Coastguard Worker    ext4fs_output, _ = proc.communicate()
86*9e94795aSAndroid Build Coastguard Worker    self.assertEqual(0, proc.returncode)
87*9e94795aSAndroid Build Coastguard Worker
88*9e94795aSAndroid Build Coastguard Worker    prop_dict = {
89*9e94795aSAndroid Build Coastguard Worker        'fs_type' : 'ext4',
90*9e94795aSAndroid Build Coastguard Worker        'partition_headroom' : '40960',
91*9e94795aSAndroid Build Coastguard Worker        'mount_point' : 'system',
92*9e94795aSAndroid Build Coastguard Worker    }
93*9e94795aSAndroid Build Coastguard Worker    CheckHeadroom(ext4fs_output, prop_dict)
94*9e94795aSAndroid Build Coastguard Worker
95*9e94795aSAndroid Build Coastguard Worker    prop_dict = {
96*9e94795aSAndroid Build Coastguard Worker        'fs_type' : 'ext4',
97*9e94795aSAndroid Build Coastguard Worker        'partition_headroom' : '413696',
98*9e94795aSAndroid Build Coastguard Worker        'mount_point' : 'system',
99*9e94795aSAndroid Build Coastguard Worker    }
100*9e94795aSAndroid Build Coastguard Worker    self.assertRaises(BuildImageError, CheckHeadroom, ext4fs_output, prop_dict)
101*9e94795aSAndroid Build Coastguard Worker
102*9e94795aSAndroid Build Coastguard Worker  def test_SetUpInDirAndFsConfig_NonSystem(self):
103*9e94795aSAndroid Build Coastguard Worker    prop_dict = {
104*9e94795aSAndroid Build Coastguard Worker        'fs_config': 'fs-config',
105*9e94795aSAndroid Build Coastguard Worker        'mount_point': 'vendor',
106*9e94795aSAndroid Build Coastguard Worker    }
107*9e94795aSAndroid Build Coastguard Worker    in_dir, fs_config = SetUpInDirAndFsConfig('/path/to/in_dir', prop_dict)
108*9e94795aSAndroid Build Coastguard Worker    self.assertEqual('/path/to/in_dir', in_dir)
109*9e94795aSAndroid Build Coastguard Worker    self.assertEqual('fs-config', fs_config)
110*9e94795aSAndroid Build Coastguard Worker    self.assertEqual('vendor', prop_dict['mount_point'])
111*9e94795aSAndroid Build Coastguard Worker
112*9e94795aSAndroid Build Coastguard Worker  @staticmethod
113*9e94795aSAndroid Build Coastguard Worker  def _gen_fs_config(partition):
114*9e94795aSAndroid Build Coastguard Worker    fs_config = common.MakeTempFile(suffix='.txt')
115*9e94795aSAndroid Build Coastguard Worker    with open(fs_config, 'w') as fs_config_fp:
116*9e94795aSAndroid Build Coastguard Worker      fs_config_fp.write('fs-config-{}\n'.format(partition))
117*9e94795aSAndroid Build Coastguard Worker    return fs_config
118*9e94795aSAndroid Build Coastguard Worker
119*9e94795aSAndroid Build Coastguard Worker  def test_SetUpInDirAndFsConfig(self):
120*9e94795aSAndroid Build Coastguard Worker    root_dir = common.MakeTempDir()
121*9e94795aSAndroid Build Coastguard Worker    with open(os.path.join(root_dir, 'init'), 'w') as init_fp:
122*9e94795aSAndroid Build Coastguard Worker      init_fp.write('init')
123*9e94795aSAndroid Build Coastguard Worker
124*9e94795aSAndroid Build Coastguard Worker    origin_in = common.MakeTempDir()
125*9e94795aSAndroid Build Coastguard Worker    with open(os.path.join(origin_in, 'file'), 'w') as in_fp:
126*9e94795aSAndroid Build Coastguard Worker      in_fp.write('system-file')
127*9e94795aSAndroid Build Coastguard Worker    os.symlink('../etc', os.path.join(origin_in, 'symlink'))
128*9e94795aSAndroid Build Coastguard Worker
129*9e94795aSAndroid Build Coastguard Worker    fs_config_system = self._gen_fs_config('system')
130*9e94795aSAndroid Build Coastguard Worker
131*9e94795aSAndroid Build Coastguard Worker    prop_dict = {
132*9e94795aSAndroid Build Coastguard Worker        'fs_config': fs_config_system,
133*9e94795aSAndroid Build Coastguard Worker        'mount_point': 'system',
134*9e94795aSAndroid Build Coastguard Worker        'root_dir': root_dir,
135*9e94795aSAndroid Build Coastguard Worker    }
136*9e94795aSAndroid Build Coastguard Worker    in_dir, fs_config = SetUpInDirAndFsConfig(origin_in, prop_dict)
137*9e94795aSAndroid Build Coastguard Worker
138*9e94795aSAndroid Build Coastguard Worker    self.assertTrue(filecmp.cmp(
139*9e94795aSAndroid Build Coastguard Worker        os.path.join(in_dir, 'init'), os.path.join(root_dir, 'init')))
140*9e94795aSAndroid Build Coastguard Worker    self.assertTrue(filecmp.cmp(
141*9e94795aSAndroid Build Coastguard Worker        os.path.join(in_dir, 'system', 'file'),
142*9e94795aSAndroid Build Coastguard Worker        os.path.join(origin_in, 'file')))
143*9e94795aSAndroid Build Coastguard Worker    self.assertTrue(os.path.islink(os.path.join(in_dir, 'system', 'symlink')))
144*9e94795aSAndroid Build Coastguard Worker
145*9e94795aSAndroid Build Coastguard Worker    self.assertTrue(filecmp.cmp(fs_config_system, fs_config))
146*9e94795aSAndroid Build Coastguard Worker    self.assertEqual('/', prop_dict['mount_point'])
147*9e94795aSAndroid Build Coastguard Worker
148*9e94795aSAndroid Build Coastguard Worker  def test_SetUpInDirAndFsConfig_WithRootFsConfig(self):
149*9e94795aSAndroid Build Coastguard Worker    root_dir = common.MakeTempDir()
150*9e94795aSAndroid Build Coastguard Worker    with open(os.path.join(root_dir, 'init'), 'w') as init_fp:
151*9e94795aSAndroid Build Coastguard Worker      init_fp.write('init')
152*9e94795aSAndroid Build Coastguard Worker
153*9e94795aSAndroid Build Coastguard Worker    origin_in = common.MakeTempDir()
154*9e94795aSAndroid Build Coastguard Worker    with open(os.path.join(origin_in, 'file'), 'w') as in_fp:
155*9e94795aSAndroid Build Coastguard Worker      in_fp.write('system-file')
156*9e94795aSAndroid Build Coastguard Worker    os.symlink('../etc', os.path.join(origin_in, 'symlink'))
157*9e94795aSAndroid Build Coastguard Worker
158*9e94795aSAndroid Build Coastguard Worker    fs_config_system = self._gen_fs_config('system')
159*9e94795aSAndroid Build Coastguard Worker    fs_config_root = self._gen_fs_config('root')
160*9e94795aSAndroid Build Coastguard Worker
161*9e94795aSAndroid Build Coastguard Worker    prop_dict = {
162*9e94795aSAndroid Build Coastguard Worker        'fs_config': fs_config_system,
163*9e94795aSAndroid Build Coastguard Worker        'mount_point': 'system',
164*9e94795aSAndroid Build Coastguard Worker        'root_dir': root_dir,
165*9e94795aSAndroid Build Coastguard Worker        'root_fs_config': fs_config_root,
166*9e94795aSAndroid Build Coastguard Worker    }
167*9e94795aSAndroid Build Coastguard Worker    in_dir, fs_config = SetUpInDirAndFsConfig(origin_in, prop_dict)
168*9e94795aSAndroid Build Coastguard Worker
169*9e94795aSAndroid Build Coastguard Worker    self.assertTrue(filecmp.cmp(
170*9e94795aSAndroid Build Coastguard Worker        os.path.join(in_dir, 'init'), os.path.join(root_dir, 'init')))
171*9e94795aSAndroid Build Coastguard Worker    self.assertTrue(filecmp.cmp(
172*9e94795aSAndroid Build Coastguard Worker        os.path.join(in_dir, 'system', 'file'),
173*9e94795aSAndroid Build Coastguard Worker        os.path.join(origin_in, 'file')))
174*9e94795aSAndroid Build Coastguard Worker    self.assertTrue(os.path.islink(os.path.join(in_dir, 'system', 'symlink')))
175*9e94795aSAndroid Build Coastguard Worker
176*9e94795aSAndroid Build Coastguard Worker    with open(fs_config) as fs_config_fp:
177*9e94795aSAndroid Build Coastguard Worker      fs_config_data = fs_config_fp.readlines()
178*9e94795aSAndroid Build Coastguard Worker    self.assertIn('fs-config-system\n', fs_config_data)
179*9e94795aSAndroid Build Coastguard Worker    self.assertIn('fs-config-root\n', fs_config_data)
180*9e94795aSAndroid Build Coastguard Worker    self.assertEqual('/', prop_dict['mount_point'])
181*9e94795aSAndroid Build Coastguard Worker
182*9e94795aSAndroid Build Coastguard Worker  @test_utils.SkipIfExternalToolsUnavailable()
183*9e94795aSAndroid Build Coastguard Worker  def test_GetFilesystemCharacteristics(self):
184*9e94795aSAndroid Build Coastguard Worker    input_dir = common.MakeTempDir()
185*9e94795aSAndroid Build Coastguard Worker    output_image = common.MakeTempFile(suffix='.img')
186*9e94795aSAndroid Build Coastguard Worker    command = ['mkuserimg_mke2fs', input_dir, output_image, 'ext4',
187*9e94795aSAndroid Build Coastguard Worker               '/system', '409600', '-j', '0']
188*9e94795aSAndroid Build Coastguard Worker    proc = common.Run(command)
189*9e94795aSAndroid Build Coastguard Worker    proc.communicate()
190*9e94795aSAndroid Build Coastguard Worker    self.assertEqual(0, proc.returncode)
191*9e94795aSAndroid Build Coastguard Worker
192*9e94795aSAndroid Build Coastguard Worker    output_file = common.MakeTempFile(suffix='.img')
193*9e94795aSAndroid Build Coastguard Worker    cmd = ["img2simg", output_image, output_file]
194*9e94795aSAndroid Build Coastguard Worker    p = common.Run(cmd)
195*9e94795aSAndroid Build Coastguard Worker    p.communicate()
196*9e94795aSAndroid Build Coastguard Worker    self.assertEqual(0, p.returncode)
197*9e94795aSAndroid Build Coastguard Worker
198*9e94795aSAndroid Build Coastguard Worker    fs_dict = GetFilesystemCharacteristics('ext4', output_file)
199*9e94795aSAndroid Build Coastguard Worker    self.assertEqual(int(fs_dict['Block size']), 4096)
200*9e94795aSAndroid Build Coastguard Worker    self.assertGreaterEqual(int(fs_dict['Free blocks']), 0) # expect ~88
201*9e94795aSAndroid Build Coastguard Worker    self.assertGreater(int(fs_dict['Inode count']), 0)      # expect ~64
202*9e94795aSAndroid Build Coastguard Worker    self.assertGreaterEqual(int(fs_dict['Free inodes']), 0) # expect ~53
203*9e94795aSAndroid Build Coastguard Worker    self.assertGreater(int(fs_dict['Inode count']), int(fs_dict['Free inodes']))
204