1import infra.basetest 2import re 3from tests.init.base import InitSystemBase as InitSystemBase 4 5 6# In the following tests, the read-only cases use the default settings, 7# which historically used both a factory to populate a tmpfs on /var, 8# and pre-populated /var at buildtime. Since these are the default 9# settings, and they proved to generate a system that ultimately boots, 10# we still want to keep testing that. See later, below, for the 11# specialised test cases. 12 13class InitSystemSystemdBase(InitSystemBase): 14 config = \ 15 """ 16 BR2_arm=y 17 BR2_cortex_a9=y 18 BR2_ARM_ENABLE_VFP=y 19 BR2_TOOLCHAIN_EXTERNAL=y 20 BR2_TOOLCHAIN_EXTERNAL_BOOTLIN=y 21 BR2_INIT_SYSTEMD=y 22 BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0" 23 # BR2_TARGET_ROOTFS_TAR is not set 24 BR2_PER_PACKAGE_DIRECTORIES=y 25 """ 26 27 def check_systemd(self, fs): 28 if "BR2_LINUX_KERNEL=y" in self.config: 29 self.start_emulator(fs, "zImage", "vexpress-v2p-ca9") 30 else: 31 self.start_emulator(fs) 32 self.check_init("/lib/systemd/systemd") 33 34 # Test all units are OK 35 output, _ = self.emulator.run("systemctl --no-pager --failed --no-legend") 36 self.assertEqual(len(output), 0) 37 38 # Test we can reach the DBus daemon 39 self.assertRunOk("busctl --no-pager") 40 41 # Test we can read at least one line from the journal 42 output, _ = self.emulator.run("journalctl --no-pager --lines 1 --quiet") 43 self.assertEqual(len(output), 1) 44 45 # Check the network is up 46 self.check_network("eth0") 47 48 49class TestInitSystemSystemdRoNetworkd(InitSystemSystemdBase): 50 config = InitSystemSystemdBase.config + \ 51 """ 52 BR2_SYSTEM_DHCP="eth0" 53 # BR2_TARGET_GENERIC_REMOUNT_ROOTFS_RW is not set 54 BR2_TARGET_ROOTFS_SQUASHFS=y 55 """ 56 57 def test_run(self): 58 self.check_systemd("squashfs") 59 60 61class TestInitSystemSystemdRwNetworkd(InitSystemSystemdBase): 62 config = InitSystemSystemdBase.config + \ 63 """ 64 BR2_SYSTEM_DHCP="eth0" 65 BR2_TARGET_ROOTFS_EXT2=y 66 """ 67 68 def test_run(self): 69 self.check_systemd("ext2") 70 71 72class TestInitSystemSystemdRoIfupdown(InitSystemSystemdBase): 73 config = InitSystemSystemdBase.config + \ 74 """ 75 BR2_SYSTEM_DHCP="eth0" 76 # BR2_PACKAGE_SYSTEMD_NETWORKD is not set 77 # BR2_TARGET_GENERIC_REMOUNT_ROOTFS_RW is not set 78 BR2_TARGET_ROOTFS_SQUASHFS=y 79 """ 80 81 def test_run(self): 82 self.check_systemd("squashfs") 83 84 85class TestInitSystemSystemdRoIfupdownDbusbroker(TestInitSystemSystemdRoIfupdown): 86 config = TestInitSystemSystemdRoIfupdown.config + \ 87 """ 88 BR2_PACKAGE_DBUS_BROKER=y 89 """ 90 91 def test_run(self): 92 # Parent class' test_run() method does exactly that, no more: 93 self.check_systemd("squashfs") 94 95 # Check that the dbus-broker daemon is running as non-root 96 cmd = "find /proc/$(pidof dbus-broker) -maxdepth 1 -name exe -user dbus" 97 out, _ = self.emulator.run(cmd) 98 self.assertEqual(len(out), 1) 99 100 101class TestInitSystemSystemdRoIfupdownDbusbrokerDbus(TestInitSystemSystemdRoIfupdownDbusbroker): 102 config = TestInitSystemSystemdRoIfupdownDbusbroker.config + \ 103 """ 104 BR2_PACKAGE_DBUS=y 105 """ 106 107 108class TestInitSystemSystemdRwIfupdown(InitSystemSystemdBase): 109 config = InitSystemSystemdBase.config + \ 110 """ 111 BR2_SYSTEM_DHCP="eth0" 112 # BR2_PACKAGE_SYSTEMD_NETWORKD is not set 113 BR2_TARGET_ROOTFS_EXT2=y 114 """ 115 116 def test_run(self): 117 self.check_systemd("ext2") 118 119 120class TestInitSystemSystemdRwIfupdownDbusbroker(TestInitSystemSystemdRwIfupdown): 121 config = TestInitSystemSystemdRwIfupdown.config + \ 122 """ 123 BR2_PACKAGE_DBUS_BROKER=y 124 """ 125 126 def test_run(self): 127 # Parent class' test_run() method does exactly that, no more: 128 self.check_systemd("ext2") 129 130 # Check that the dbus-broker daemon is running as non-root 131 cmd = "find /proc/$(pidof dbus-broker) -maxdepth 1 -name exe -user dbus" 132 out, _ = self.emulator.run(cmd) 133 self.assertEqual(len(out), 1) 134 135 136class TestInitSystemSystemdRwIfupdownDbusbrokerDbus(TestInitSystemSystemdRwIfupdownDbusbroker): 137 config = TestInitSystemSystemdRwIfupdownDbusbroker.config + \ 138 """ 139 BR2_PACKAGE_DBUS=y 140 """ 141 142 143class TestInitSystemSystemdRoFull(InitSystemSystemdBase): 144 config = InitSystemSystemdBase.config + \ 145 """ 146 BR2_SYSTEM_DHCP="eth0" 147 # BR2_TARGET_GENERIC_REMOUNT_ROOTFS_RW is not set 148 BR2_PACKAGE_SYSTEMD_JOURNAL_REMOTE=y 149 BR2_PACKAGE_SYSTEMD_BACKLIGHT=y 150 BR2_PACKAGE_SYSTEMD_BINFMT=y 151 BR2_PACKAGE_SYSTEMD_COREDUMP=y 152 BR2_PACKAGE_SYSTEMD_FIRSTBOOT=y 153 BR2_PACKAGE_SYSTEMD_HIBERNATE=y 154 BR2_PACKAGE_SYSTEMD_IMPORTD=y 155 BR2_PACKAGE_SYSTEMD_LOCALED=y 156 BR2_PACKAGE_SYSTEMD_LOGIND=y 157 BR2_PACKAGE_SYSTEMD_MACHINED=y 158 BR2_PACKAGE_SYSTEMD_POLKIT=y 159 BR2_PACKAGE_SYSTEMD_QUOTACHECK=y 160 BR2_PACKAGE_SYSTEMD_RANDOMSEED=y 161 BR2_PACKAGE_SYSTEMD_RFKILL=y 162 BR2_PACKAGE_SYSTEMD_SMACK_SUPPORT=y 163 BR2_PACKAGE_SYSTEMD_SYSUSERS=y 164 BR2_PACKAGE_SYSTEMD_VCONSOLE=y 165 BR2_TARGET_ROOTFS_SQUASHFS=y 166 """ 167 168 def test_run(self): 169 self.check_systemd("squashfs") 170 171 172class TestInitSystemSystemdRwFull(InitSystemSystemdBase): 173 config = InitSystemSystemdBase.config + \ 174 """ 175 BR2_SYSTEM_DHCP="eth0" 176 BR2_PACKAGE_SYSTEMD_JOURNAL_REMOTE=y 177 BR2_PACKAGE_SYSTEMD_BACKLIGHT=y 178 BR2_PACKAGE_SYSTEMD_BINFMT=y 179 BR2_PACKAGE_SYSTEMD_COREDUMP=y 180 BR2_PACKAGE_SYSTEMD_FIRSTBOOT=y 181 BR2_PACKAGE_SYSTEMD_HIBERNATE=y 182 BR2_PACKAGE_SYSTEMD_IMPORTD=y 183 BR2_PACKAGE_SYSTEMD_LOCALED=y 184 BR2_PACKAGE_SYSTEMD_LOGIND=y 185 BR2_PACKAGE_SYSTEMD_MACHINED=y 186 BR2_PACKAGE_SYSTEMD_POLKIT=y 187 BR2_PACKAGE_SYSTEMD_QUOTACHECK=y 188 BR2_PACKAGE_SYSTEMD_RANDOMSEED=y 189 BR2_PACKAGE_SYSTEMD_RFKILL=y 190 BR2_PACKAGE_SYSTEMD_SMACK_SUPPORT=y 191 BR2_PACKAGE_SYSTEMD_SYSUSERS=y 192 BR2_PACKAGE_SYSTEMD_VCONSOLE=y 193 BR2_TARGET_ROOTFS_EXT2=y 194 """ 195 196 def test_run(self): 197 self.check_systemd("ext2") 198 199 200# The following tests are all about read-only rootfs, and exercise either 201# using an un-populated factory for /var, or an overlaysfs ontop of a 202# pre-populated /var. They all specialise the TestInitSystemSystemdRo* 203# test cases above. 204 205 206# Helper class for factory-based tests 207class InitSystemSystemdBaseFactory(): 208 config = \ 209 """ 210 # BR2_INIT_SYSTEMD_POPULATE_TMPFILES is not set 211 BR2_ROOTFS_OVERLAY="{}" 212 """.format(infra.filepath("tests/init/systemd-factory")) 213 214 def test_run(self): 215 super().test_run() 216 217 # This one must be executed on the target, to check that 218 # the factory feature works as expected 219 out, exit_code = self.emulator.run("cat /var/foo/bar") 220 self.assertEqual(exit_code, 0) 221 self.assertEqual(out[0], "foobar") 222 223 # /var/foo/bar is from the /var factory 224 _, exit_code = self.emulator.run("test -e /usr/share/factory/var/foo/bar") 225 self.assertEqual(exit_code, 0) 226 227 # We can write in /var/foo/bar 228 _, exit_code = self.emulator.run("echo barfoo >/var/foo/bar") 229 self.assertEqual(exit_code, 0) 230 # ... and it contains the new content 231 out, exit_code = self.emulator.run("cat /var/foo/bar") 232 self.assertEqual(exit_code, 0) 233 self.assertEqual(out[0], "barfoo") 234 # ... but the factory is umodified 235 out, exit_code = self.emulator.run("cat /usr/share/factory/var/foo/bar") 236 self.assertEqual(exit_code, 0) 237 self.assertEqual(out[0], "foobar") 238 239 240class TestInitSystemSystemdRoNetworkdFactory( 241 InitSystemSystemdBaseFactory, 242 TestInitSystemSystemdRoNetworkd, 243): 244 config = InitSystemSystemdBaseFactory.config + \ 245 TestInitSystemSystemdRoNetworkd.config 246 247 248class TestInitSystemSystemdRoIfupdownFactory( 249 InitSystemSystemdBaseFactory, 250 TestInitSystemSystemdRoIfupdown, 251): 252 config = InitSystemSystemdBaseFactory.config + \ 253 TestInitSystemSystemdRoIfupdown.config 254 255 256class TestInitSystemSystemdRoIfupdownDbusbrokerFactory( 257 InitSystemSystemdBaseFactory, 258 TestInitSystemSystemdRoIfupdownDbusbroker, 259): 260 config = InitSystemSystemdBaseFactory.config + \ 261 TestInitSystemSystemdRoIfupdownDbusbroker.config 262 263 264class TestInitSystemSystemdRoIfupdownDbusbrokerDbusFactory( 265 InitSystemSystemdBaseFactory, 266 TestInitSystemSystemdRoIfupdownDbusbrokerDbus, 267): 268 config = InitSystemSystemdBaseFactory.config + \ 269 TestInitSystemSystemdRoIfupdownDbusbrokerDbus.config 270 271 272class TestInitSystemSystemdRoFullFactory( 273 InitSystemSystemdBaseFactory, 274 TestInitSystemSystemdRoFull, 275): 276 config = InitSystemSystemdBaseFactory.config + \ 277 TestInitSystemSystemdRoFull.config 278 279 280# Helper class for overlayfs-based tests 281class InitSystemSystemdBaseOverlayfs(): 282 config = \ 283 """ 284 # BR2_INIT_SYSTEMD_VAR_FACTORY is not set 285 BR2_INIT_SYSTEMD_VAR_OVERLAYFS=y 286 BR2_ROOTFS_OVERLAY="{}" 287 BR2_LINUX_KERNEL=y 288 BR2_LINUX_KERNEL_CUSTOM_VERSION=y 289 BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="5.10.202" 290 BR2_LINUX_KERNEL_DEFCONFIG="vexpress" 291 BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{}" 292 BR2_LINUX_KERNEL_DTS_SUPPORT=y 293 BR2_LINUX_KERNEL_INTREE_DTS_NAME="vexpress-v2p-ca9" 294 """.format(infra.filepath("tests/init/systemd-factory"), 295 infra.filepath("conf/overlayfs-kernel-fragment.config")) 296 297 def test_run(self): 298 super().test_run() 299 300 # This one must be executed on the target, to check that 301 # the tmpfiles pre-populate works as expected 302 out, exit_code = self.emulator.run("cat /var/foo/bar") 303 self.assertEqual(exit_code, 0) 304 self.assertEqual(out[0], "foobar") 305 306 # /var/foo/bar is from the pre-populated /var, so it should 307 # not be present in the upper of the overlay 308 _, exit_code = self.emulator.run("test -e /run/buildroot/mounts/var/upper/foo/bar") 309 self.assertNotEqual(exit_code, 0) 310 311 # We can write in /var/foo/bar 312 _, exit_code = self.emulator.run("echo barfoo >/var/foo/bar") 313 self.assertEqual(exit_code, 0) 314 # ... and it contains the new content 315 out, exit_code = self.emulator.run("cat /var/foo/bar") 316 self.assertEqual(exit_code, 0) 317 self.assertEqual(out[0], "barfoo") 318 # ... and it to appears in the upper 319 _, exit_code = self.emulator.run("test -e /run/buildroot/mounts/var/upper/foo/bar") 320 self.assertEqual(exit_code, 0) 321 # ... with the new content 322 out, exit_code = self.emulator.run("cat /run/buildroot/mounts/var/upper/foo/bar") 323 self.assertEqual(exit_code, 0) 324 self.assertEqual(out[0], "barfoo") 325 # ... while the lower still has the oldcontent 326 out, exit_code = self.emulator.run("cat /run/buildroot/mounts/var/lower/foo/bar") 327 self.assertEqual(exit_code, 0) 328 self.assertEqual(out[0], "foobar") 329 330 331class TestInitSystemSystemdRoNetworkdOverlayfs( 332 InitSystemSystemdBaseOverlayfs, 333 TestInitSystemSystemdRoNetworkd, 334): 335 config = InitSystemSystemdBaseOverlayfs.config + \ 336 TestInitSystemSystemdRoNetworkd.config 337 338 339class TestInitSystemSystemdRoIfupdownOverlayfs( 340 InitSystemSystemdBaseOverlayfs, 341 TestInitSystemSystemdRoIfupdown, 342): 343 config = InitSystemSystemdBaseOverlayfs.config + \ 344 TestInitSystemSystemdRoIfupdown.config 345 346 347class TestInitSystemSystemdRoIfupdownDbusbrokerOverlayfs( 348 InitSystemSystemdBaseOverlayfs, 349 TestInitSystemSystemdRoIfupdownDbusbroker, 350): 351 config = InitSystemSystemdBaseOverlayfs.config + \ 352 TestInitSystemSystemdRoIfupdownDbusbroker.config 353 354 355class TestInitSystemSystemdRoIfupdownDbusbrokerDbusOverlayfs( 356 InitSystemSystemdBaseOverlayfs, 357 TestInitSystemSystemdRoIfupdownDbusbrokerDbus, 358): 359 config = InitSystemSystemdBaseOverlayfs.config + \ 360 TestInitSystemSystemdRoIfupdownDbusbrokerDbus.config 361 362 363class TestInitSystemSystemdRoFullOverlayfs( 364 InitSystemSystemdBaseOverlayfs, 365 TestInitSystemSystemdRoFull, 366): 367 config = InitSystemSystemdBaseOverlayfs.config + \ 368 TestInitSystemSystemdRoFull.config 369 370 371class InitSystemSystemdBaseOverlayfsVarBacking(InitSystemBase): 372 @classmethod 373 def gen_config(cls, overlaydir: str) -> str: 374 return re.sub( 375 r'^\s*BR2_ROOTFS_OVERLAY="(.*)"$', 376 'BR2_ROOTFS_OVERLAY="\\1 {}"'.format(infra.filepath(overlaydir)), 377 TestInitSystemSystemdRoFullOverlayfs.config, 378 flags=re.MULTILINE, 379 ) 380 381 def check_var_mounted(self): 382 self.assertRunOk("grep '^other-var-backing-store /run/buildroot/mounts/var tmpfs' /proc/mounts") 383 384 385class TestInitSystemSystemdRoFullOverlayfsVarBackingMountUnit( 386 TestInitSystemSystemdRoFullOverlayfs, 387 InitSystemSystemdBaseOverlayfsVarBacking, 388): 389 config = InitSystemSystemdBaseOverlayfsVarBacking.gen_config( 390 'tests/init/systemd-overlay-mount-unit', 391 ) 392 393 def test_run(self): 394 super().test_run() 395 self.check_var_mounted() 396 397 398class TestInitSystemSystemdRoFullOverlayfsVarBackingFstab( 399 TestInitSystemSystemdRoFullOverlayfs, 400 InitSystemSystemdBaseOverlayfsVarBacking, 401): 402 config = InitSystemSystemdBaseOverlayfsVarBacking.gen_config( 403 'tests/init/systemd-overlay-fstab', 404 ) 405 406 def test_run(self): 407 super().test_run() 408 self.check_var_mounted() 409