blob: 415e0315fc0be3fc2f0a0c82da516a86c320fc48 [file] [log] [blame]
Brad Bishopc342db32019-05-15 21:57:59 -04001#
2# SPDX-License-Identifier: MIT
3#
4
Brad Bishopd7bf8c12018-02-25 22:55:05 -05005from oeqa.selftest.case import OESelftestTestCase
6from oeqa.utils.commands import runCmd, bitbake, get_bb_var, runqemu
Brad Bishopd7bf8c12018-02-25 22:55:05 -05007from oeqa.utils.sshcontrol import SSHControl
Andrew Geissler4c19ea12020-10-27 13:52:24 -05008import glob
Brad Bishopd7bf8c12018-02-25 22:55:05 -05009import os
10import json
11
12class ImageFeatures(OESelftestTestCase):
13
14 test_user = 'tester'
15 root_user = 'root'
16
Brad Bishopd7bf8c12018-02-25 22:55:05 -050017 def test_non_root_user_can_connect_via_ssh_without_password(self):
18 """
19 Summary: Check if non root user can connect via ssh without password
20 Expected: 1. Connection to the image via ssh using root user without providing a password should be allowed.
21 2. Connection to the image via ssh using tester user without providing a password should be allowed.
22 Product: oe-core
23 Author: Ionut Chisanovici <ionutx.chisanovici@intel.com>
24 AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
25 """
26
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080027 features = 'EXTRA_IMAGE_FEATURES = "ssh-server-openssh empty-root-password allow-empty-password allow-root-login"\n'
Brad Bishopd7bf8c12018-02-25 22:55:05 -050028 features += 'INHERIT += "extrausers"\n'
29 features += 'EXTRA_USERS_PARAMS = "useradd -p \'\' {}; usermod -s /bin/sh {};"'.format(self.test_user, self.test_user)
30 self.write_config(features)
31
32 # Build a core-image-minimal
33 bitbake('core-image-minimal')
34
35 with runqemu("core-image-minimal") as qemu:
36 # Attempt to ssh with each user into qemu with empty password
37 for user in [self.root_user, self.test_user]:
38 ssh = SSHControl(ip=qemu.ip, logfile=qemu.sshlog, user=user)
39 status, output = ssh.run("true")
40 self.assertEqual(status, 0, 'ssh to user %s failed with %s' % (user, output))
41
Brad Bishopd7bf8c12018-02-25 22:55:05 -050042 def test_all_users_can_connect_via_ssh_without_password(self):
43 """
44 Summary: Check if all users can connect via ssh without password
45 Expected: 1. Connection to the image via ssh using root user without providing a password should NOT be allowed.
46 2. Connection to the image via ssh using tester user without providing a password should be allowed.
47 Product: oe-core
48 Author: Ionut Chisanovici <ionutx.chisanovici@intel.com>
49 AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
50 """
51
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080052 features = 'EXTRA_IMAGE_FEATURES = "ssh-server-openssh allow-empty-password allow-root-login"\n'
Brad Bishopd7bf8c12018-02-25 22:55:05 -050053 features += 'INHERIT += "extrausers"\n'
54 features += 'EXTRA_USERS_PARAMS = "useradd -p \'\' {}; usermod -s /bin/sh {};"'.format(self.test_user, self.test_user)
55 self.write_config(features)
56
57 # Build a core-image-minimal
58 bitbake('core-image-minimal')
59
60 with runqemu("core-image-minimal") as qemu:
61 # Attempt to ssh with each user into qemu with empty password
62 for user in [self.root_user, self.test_user]:
63 ssh = SSHControl(ip=qemu.ip, logfile=qemu.sshlog, user=user)
64 status, output = ssh.run("true")
65 if user == 'root':
66 self.assertNotEqual(status, 0, 'ssh to user root was allowed when it should not have been')
67 else:
68 self.assertEqual(status, 0, 'ssh to user tester failed with %s' % output)
69
70
Brad Bishopd7bf8c12018-02-25 22:55:05 -050071 def test_clutter_image_can_be_built(self):
72 """
73 Summary: Check if clutter image can be built
74 Expected: 1. core-image-clutter can be built
75 Product: oe-core
76 Author: Ionut Chisanovici <ionutx.chisanovici@intel.com>
77 AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
78 """
79
80 # Build a core-image-clutter
81 bitbake('core-image-clutter')
82
Brad Bishopd7bf8c12018-02-25 22:55:05 -050083 def test_wayland_support_in_image(self):
84 """
85 Summary: Check Wayland support in image
86 Expected: 1. Wayland image can be build
87 2. Wayland feature can be installed
88 Product: oe-core
89 Author: Ionut Chisanovici <ionutx.chisanovici@intel.com>
90 AutomatedBy: Daniel Istrate <daniel.alexandrux.istrate@intel.com>
91 """
92
93 distro_features = get_bb_var('DISTRO_FEATURES')
94 if not ('opengl' in distro_features and 'wayland' in distro_features):
95 self.skipTest('neither opengl nor wayland present on DISTRO_FEATURES so core-image-weston cannot be built')
96
97 # Build a core-image-weston
98 bitbake('core-image-weston')
99
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500100 def test_bmap(self):
101 """
102 Summary: Check bmap support
103 Expected: 1. core-image-minimal can be build with bmap support
104 2. core-image-minimal is sparse
105 Product: oe-core
106 Author: Ed Bartosh <ed.bartosh@linux.intel.com>
107 """
108
109 features = 'IMAGE_FSTYPES += " ext4 ext4.bmap ext4.bmap.gz"'
110 self.write_config(features)
111
112 image_name = 'core-image-minimal'
113 bitbake(image_name)
114
115 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
116 link_name = get_bb_var('IMAGE_LINK_NAME', image_name)
117 image_path = os.path.join(deploy_dir_image, "%s.ext4" % link_name)
118 bmap_path = "%s.bmap" % image_path
119 gzip_path = "%s.gz" % bmap_path
120
121 # check if result image, bmap and bmap.gz files are in deploy directory
122 self.assertTrue(os.path.exists(image_path))
123 self.assertTrue(os.path.exists(bmap_path))
124 self.assertTrue(os.path.exists(gzip_path))
125
126 # check if result image is sparse
127 image_stat = os.stat(image_path)
Brad Bishop64c979e2019-11-04 13:55:29 -0500128 self.assertGreater(image_stat.st_size, image_stat.st_blocks * 512)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500129
130 # check if the resulting gzip is valid
131 self.assertTrue(runCmd('gzip -t %s' % gzip_path))
132
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500133 def test_hypervisor_fmts(self):
134 """
135 Summary: Check various hypervisor formats
136 Expected: 1. core-image-minimal can be built with vmdk, vdi and
137 qcow2 support.
138 2. qemu-img says each image has the expected format
139 Product: oe-core
140 Author: Tom Rini <trini@konsulko.com>
141 """
142
143 img_types = [ 'vmdk', 'vdi', 'qcow2' ]
144 features = ""
145 for itype in img_types:
146 features += 'IMAGE_FSTYPES += "wic.%s"\n' % itype
147 self.write_config(features)
148
149 image_name = 'core-image-minimal'
150 bitbake(image_name)
151
152 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
153 link_name = get_bb_var('IMAGE_LINK_NAME', image_name)
154 for itype in img_types:
155 image_path = os.path.join(deploy_dir_image, "%s.wic.%s" %
156 (link_name, itype))
157
158 # check if result image file is in deploy directory
159 self.assertTrue(os.path.exists(image_path))
160
161 # check if result image is vmdk
162 sysroot = get_bb_var('STAGING_DIR_NATIVE', 'core-image-minimal')
163 result = runCmd('qemu-img info --output json %s' % image_path,
164 native_sysroot=sysroot)
Brad Bishopf3f93bb2019-10-16 14:33:32 -0400165 try:
166 data = json.loads(result.output)
167 self.assertEqual(data.get('format'), itype,
168 msg="Unexpected format in '%s'" % (result.output))
169 except json.decoder.JSONDecodeError:
170 self.fail("Could not parse '%ss'" % result.output)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500171
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500172 def test_long_chain_conversion(self):
173 """
174 Summary: Check for chaining many CONVERSION_CMDs together
175 Expected: 1. core-image-minimal can be built with
176 ext4.bmap.gz.bz2.lzo.xz.u-boot and also create a
177 sha256sum
178 2. The above image has a valid sha256sum
179 Product: oe-core
180 Author: Tom Rini <trini@konsulko.com>
181 """
182
183 conv = "ext4.bmap.gz.bz2.lzo.xz.u-boot"
184 features = 'IMAGE_FSTYPES += "%s %s.sha256sum"' % (conv, conv)
185 self.write_config(features)
186
187 image_name = 'core-image-minimal'
188 bitbake(image_name)
189
190 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
191 link_name = get_bb_var('IMAGE_LINK_NAME', image_name)
192 image_path = os.path.join(deploy_dir_image, "%s.%s" %
193 (link_name, conv))
194
195 # check if resulting image is in the deploy directory
196 self.assertTrue(os.path.exists(image_path))
197 self.assertTrue(os.path.exists(image_path + ".sha256sum"))
198
199 # check if the resulting sha256sum agrees
200 self.assertTrue(runCmd('cd %s;sha256sum -c %s.%s.sha256sum' %
201 (deploy_dir_image, link_name, conv)))
202
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500203 def test_image_fstypes(self):
204 """
205 Summary: Check if image of supported image fstypes can be built
206 Expected: core-image-minimal can be built for various image types
207 Product: oe-core
208 Author: Ed Bartosh <ed.bartosh@linux.intel.com>
209 """
210 image_name = 'core-image-minimal'
211
Andrew Geissler82c905d2020-04-13 13:39:40 -0500212 all_image_types = set(get_bb_var("IMAGE_TYPES", image_name).split())
Andrew Geissler1e34c2d2020-05-29 16:02:59 -0500213 blacklist = set(('container', 'elf', 'f2fs', 'multiubi', 'tar.zst', 'wic.zst'))
Andrew Geissler82c905d2020-04-13 13:39:40 -0500214 img_types = all_image_types - blacklist
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500215
216 config = 'IMAGE_FSTYPES += "%s"\n'\
217 'MKUBIFS_ARGS ?= "-m 2048 -e 129024 -c 2047"\n'\
218 'UBINIZE_ARGS ?= "-m 2048 -p 128KiB -s 512"' % ' '.join(img_types)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500219 self.write_config(config)
220
221 bitbake(image_name)
222
223 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
224 link_name = get_bb_var('IMAGE_LINK_NAME', image_name)
225 for itype in img_types:
226 image_path = os.path.join(deploy_dir_image, "%s.%s" % (link_name, itype))
227 # check if result image is in deploy directory
228 self.assertTrue(os.path.exists(image_path),
229 "%s image %s doesn't exist" % (itype, image_path))
230
231 def test_useradd_static(self):
232 config = """
233USERADDEXTENSION = "useradd-staticids"
234USERADD_ERROR_DYNAMIC = "skip"
235USERADD_UID_TABLES += "files/static-passwd"
236USERADD_GID_TABLES += "files/static-group"
237"""
238 self.write_config(config)
239 bitbake("core-image-base")
Brad Bishop19323692019-04-05 15:28:33 -0400240
241 def test_no_busybox_base_utils(self):
242 config = """
243# Enable x11
244DISTRO_FEATURES_append += "x11"
245
246# Switch to systemd
247DISTRO_FEATURES += "systemd"
248VIRTUAL-RUNTIME_init_manager = "systemd"
249VIRTUAL-RUNTIME_initscripts = ""
250VIRTUAL-RUNTIME_syslog = ""
251VIRTUAL-RUNTIME_login_manager = "shadow-base"
252DISTRO_FEATURES_BACKFILL_CONSIDERED = "sysvinit"
253
254# Replace busybox
255PREFERRED_PROVIDER_virtual/base-utils = "packagegroup-core-base-utils"
256VIRTUAL-RUNTIME_base-utils = "packagegroup-core-base-utils"
257VIRTUAL-RUNTIME_base-utils-hwclock = "util-linux-hwclock"
258VIRTUAL-RUNTIME_base-utils-syslog = ""
259
260# Blacklist busybox
261PNBLACKLIST[busybox] = "Don't build this"
262"""
263 self.write_config(config)
264
265 bitbake("--graphviz core-image-sato")
Andrew Geisslerc182c622020-05-15 14:13:32 -0500266
Andrew Geissler706d5aa2021-02-12 15:55:30 -0600267 def test_fit_image(self):
268 """
269 Summary: Check if FIT image and Image Tree Source (its) are built
270 and the Image Tree Source has the correct fields.
271 Expected: 1. fitImage and fitImage-its can be built
272 2. The type, load address, entrypoint address and
273 default values of kernel and ramdisk are as expected
274 in the Image Tree Source. Not all the fields are tested,
275 only the key fields that wont vary between different
276 architectures.
277 Product: oe-core
278 Author: Usama Arif <usama.arif@arm.com>
279 """
280 config = """
281# Enable creation of fitImage
282KERNEL_IMAGETYPE = "Image"
283KERNEL_IMAGETYPES += " fitImage "
284KERNEL_CLASSES = " kernel-fitimage "
285
286# RAM disk variables including load address and entrypoint for kernel and RAM disk
287IMAGE_FSTYPES += "cpio.gz"
288INITRAMFS_IMAGE = "core-image-minimal"
289UBOOT_RD_LOADADDRESS = "0x88000000"
290UBOOT_RD_ENTRYPOINT = "0x88000000"
291UBOOT_LOADADDRESS = "0x80080000"
292UBOOT_ENTRYPOINT = "0x80080000"
293"""
294 self.write_config(config)
295
296 # fitImage is created as part of linux recipe
297 bitbake("virtual/kernel")
298
299 image_type = "core-image-minimal"
300 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
301 machine = get_bb_var('MACHINE')
302 fitimage_its_path = os.path.join(deploy_dir_image,
303 "fitImage-its-%s-%s-%s" % (image_type, machine, machine))
304 fitimage_path = os.path.join(deploy_dir_image,
305 "fitImage-%s-%s-%s" % (image_type, machine, machine))
306
307 self.assertTrue(os.path.exists(fitimage_its_path),
308 "%s image tree source doesn't exist" % (fitimage_its_path))
309 self.assertTrue(os.path.exists(fitimage_path),
310 "%s FIT image doesn't exist" % (fitimage_path))
311
312 # Check that the type, load address, entrypoint address and default
313 # values for kernel and ramdisk in Image Tree Source are as expected.
314 # The order of fields in the below array is important. Not all the
315 # fields are tested, only the key fields that wont vary between
316 # different architectures.
317 its_field_check = ['type = "kernel";',
318 'load = <0x80080000>;',
319 'entry = <0x80080000>;',
320 'type = "ramdisk";',
321 'load = <0x88000000>;',
322 'entry = <0x88000000>;',
323 'default = "conf@1";',
324 'kernel = "kernel@1";',
325 'ramdisk = "ramdisk@1";'
326 ]
327
328 with open(fitimage_its_path) as its_file:
329 field_index = 0
330 for line in its_file:
331 if field_index == len(its_field_check):
332 break
333 if its_field_check[field_index] in line:
334 field_index +=1
335
336 if field_index != len(its_field_check): # if its equal, the test passed
337 self.assertTrue(field_index == len(its_field_check),
338 "Fields in Image Tree Source File %s did not match, error in finding %s"
339 % (fitimage_its_path, its_field_check[field_index]))
340
Andrew Geisslerc182c622020-05-15 14:13:32 -0500341 def test_image_gen_debugfs(self):
342 """
343 Summary: Check debugfs generation
344 Expected: 1. core-image-minimal can be build with IMAGE_GEN_DEBUGFS variable set
345 2. debug filesystem is created when variable set
346 3. debug symbols available
347 Product: oe-core
348 Author: Humberto Ibarra <humberto.ibarra.lopez@intel.com>
349 Yeoh Ee Peng <ee.peng.yeoh@intel.com>
350 """
Andrew Geissler4c19ea12020-10-27 13:52:24 -0500351
Andrew Geisslerc182c622020-05-15 14:13:32 -0500352 image_name = 'core-image-minimal'
353 features = 'IMAGE_GEN_DEBUGFS = "1"\n'
354 features += 'IMAGE_FSTYPES_DEBUGFS = "tar.bz2"\n'
355 features += 'MACHINE = "genericx86-64"\n'
356 self.write_config(features)
357
358 bitbake(image_name)
359 deploy_dir_image = get_bb_var('DEPLOY_DIR_IMAGE')
360 dbg_tar_file = os.path.join(deploy_dir_image, "*-dbg.rootfs.tar.bz2")
361 debug_files = glob.glob(dbg_tar_file)
362 self.assertNotEqual(len(debug_files), 0, 'debug filesystem not generated at %s' % dbg_tar_file)
363 result = runCmd('cd %s; tar xvf %s' % (deploy_dir_image, dbg_tar_file))
364 self.assertEqual(result.status, 0, msg='Failed to extract %s: %s' % (dbg_tar_file, result.output))
365 result = runCmd('find %s -name %s' % (deploy_dir_image, "udevadm"))
366 self.assertTrue("udevadm" in result.output, msg='Failed to find udevadm: %s' % result.output)
367 dbg_symbols_targets = result.output.splitlines()
368 self.assertTrue(dbg_symbols_targets, msg='Failed to split udevadm: %s' % dbg_symbols_targets)
369 for t in dbg_symbols_targets:
370 result = runCmd('objdump --syms %s | grep debug' % t)
371 self.assertTrue("debug" in result.output, msg='Failed to find debug symbol: %s' % result.output)
Andrew Geissler4c19ea12020-10-27 13:52:24 -0500372
373 def test_empty_image(self):
374 """Test creation of image with no packages"""
375 bitbake('test-empty-image')
376 res_dir = get_bb_var('DEPLOY_DIR_IMAGE')
377 images = os.path.join(res_dir, "test-empty-image-*.manifest")
378 result = glob.glob(images)
379 with open(result[1],"r") as f:
380 self.assertEqual(len(f.read().strip()),0)