@@ -1723,6 +1723,8 @@ F: support/testing/tests/package/test_acpica/
F: support/testing/tests/package/test_brotli.py
F: support/testing/tests/package/test_bzip2.py
F: support/testing/tests/package/test_compressor_base.py
+F: support/testing/tests/package/test_criu.py
+F: support/testing/tests/package/test_criu/
F: support/testing/tests/package/test_ddrescue.py
F: support/testing/tests/package/test_ddrescue/
F: support/testing/tests/package/test_dos2unix.py
new file mode 100644
@@ -0,0 +1,127 @@
+import os
+import time
+
+import infra.basetest
+
+
+class TestCriu(infra.basetest.BRTest):
+ # Criu needs to recompile a Kernel, to enable
+ # CONFIG_CHECKPOINT_RESTORE=y
+ config = \
+ """
+ BR2_aarch64=y
+ BR2_TOOLCHAIN_EXTERNAL=y
+ BR2_TARGET_GENERIC_GETTY_PORT="ttyAMA0"
+ BR2_LINUX_KERNEL=y
+ BR2_LINUX_KERNEL_CUSTOM_VERSION=y
+ BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.53"
+ BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
+ BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
+ BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{}"
+ BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
+ BR2_PACKAGE_CRIU=y
+ BR2_PACKAGE_HOST_PYTHON3=y
+ BR2_ROOTFS_OVERLAY="{}"
+ BR2_TARGET_ROOTFS_CPIO=y
+ BR2_TARGET_ROOTFS_CPIO_GZIP=y
+ # BR2_TARGET_ROOTFS_TAR is not set
+ """.format(
+ infra.filepath("tests/package/test_criu/linux-criu.fragment"),
+ infra.filepath("tests/package/test_criu/rootfs-overlay")
+ )
+ # Define constants for the test
+ test_script_name = "criu-loop.sh"
+ test_script_path = f"/root/{test_script_name}"
+ test_flag_file = "/tmp/wait-flag"
+ test_log = "/tmp/criu-loop.log"
+ pidof_cmd = f"pidof {test_script_name}"
+ checkpoint_dir = "/root/checkpoint"
+ tail1_log_cmd = f"tail -1 {test_log}"
+ expected_log_end = "Done"
+
+ def assert_script_is_running(self):
+ # We check our script is running if the command "pidof"
+ # succeed to find a valid PID.
+ self.assertRunOk(self.pidof_cmd)
+
+ def assert_script_is_not_running(self):
+ # Conversely, the "pidof" command will fail if it cannot find
+ # a valid PID for our script.
+ _, exit_code = self.emulator.run(self.pidof_cmd)
+ self.assertNotEqual(exit_code, 0)
+
+ def test_run(self):
+ img = os.path.join(self.builddir, "images", "rootfs.cpio.gz")
+ kern = os.path.join(self.builddir, "images", "Image")
+ self.emulator.boot(arch="aarch64",
+ kernel=kern,
+ kernel_cmdline=["console=ttyAMA0"],
+ options=["-M", "virt",
+ "-cpu", "cortex-a57",
+ "-m", "256M",
+ "-initrd", img])
+ self.emulator.login()
+
+ # We check the program can execute.
+ self.assertRunOk("criu --version")
+
+ # We run the "criu check" command, which validates the kernel
+ # supports the needed features. We also add verbose logs for
+ # easier debugging.
+ self.assertRunOk("criu check -v")
+
+ # We start our test script, in a new session. Note: to make
+ # sure this test will be reliable in different execution speed
+ # conditions, the script implement a simple synchronization
+ # mechanism by creating a flag file and wait for it to be
+ # removed by this test controller.
+ cmd = f"setsid {self.test_script_path}"
+ cmd += f" < /dev/null &> {self.test_log} &"
+ self.assertRunOk(cmd)
+
+ # Let the script make few loops, then create and wait on its
+ # flag file.
+ time.sleep(3)
+
+ # Our script is supposed to be running.
+ self.assert_script_is_running()
+
+ # We dump the process tree with criu.
+ self.assertRunOk(f"mkdir -p {self.checkpoint_dir}")
+ cmd = f"criu dump -D {self.checkpoint_dir} -t $({self.pidof_cmd})"
+ self.assertRunOk(cmd)
+
+ # We check some criu image files were created.
+ self.assertRunOk(f"ls -1 --color=never {self.checkpoint_dir}/*.img")
+
+ # Our script is no longer supposed to be running (it was
+ # supposed to be stopped bu criu during the dump).
+ self.assert_script_is_not_running()
+
+ # We expect the last line of the log to NOT be "Done" yet.
+ output, exit_code = self.emulator.run(self.tail1_log_cmd)
+ self.assertEqual(exit_code, 0)
+ self.assertNotEqual(output[0], self.expected_log_end)
+
+ # We restore the process image.
+ self.assertRunOk(f"criu restore -d -D {self.checkpoint_dir}")
+
+ # Our script is supposed to be running again.
+ self.assert_script_is_running()
+
+ # We remove our test flag, to let our script to end its loop
+ # (this flag was created by the test script, while we were
+ # waiting earlier).
+ self.assertRunOk(f"rm {self.test_flag_file}")
+
+ # We wait for the script to finish its loop.
+ time.sleep(5)
+
+ # Our script is supposed to have reached its end, and
+ # exited. The script is no longer supposed to be running.
+ self.assert_script_is_not_running()
+
+ # We expect the last line of the log to be the end message.
+ output, exit_code = self.emulator.run(self.tail1_log_cmd)
+ self.assertEqual(exit_code, 0)
+ self.assertEqual(output[0], self.expected_log_end)
new file mode 100644
@@ -0,0 +1 @@
+CONFIG_CHECKPOINT_RESTORE=y
new file mode 100755
@@ -0,0 +1,15 @@
+#! /bin/sh
+set -eu
+echo "Start"
+for LOOP in $(seq 6) ; do
+ echo "Loop $LOOP"
+ if [ "$LOOP" -eq 3 ] ; then
+ touch /tmp/wait-flag
+ fi
+ while [ -e /tmp/wait-flag ] ; do
+ sleep 1
+ echo "Waiting..."
+ done
+ sleep 1
+done
+echo "Done"
Cc: Thomas Petazzoni <thomas.petazzoni@bootlin.com> Cc: Marcus Folkesson <marcus.folkesson@gmail.com> Signed-off-by: Julien Olivain <ju.o@free.fr> --- This test was suggested by Thomas in [1] during the criu package proposal in [2]. criu is not accepted yet. This is a first version of the test for review. Minor rework is expected to align the the final criu package patch. Tested on branch master at commit c89d7a2, on top of criu patch [2], with command: support/testing/run-tests \ -d dl -o output_folder \ tests.package.test_criu ... OK [1] https://lists.buildroot.org/pipermail/buildroot/2023-September/674567.html [2] https://patchwork.ozlabs.org/project/buildroot/patch/20230910193725.1435827-1-marcus.folkesson@gmail.com/ --- DEVELOPERS | 2 + support/testing/tests/package/test_criu.py | 127 ++++++++++++++++++ .../package/test_criu/linux-criu.fragment | 1 + .../rootfs-overlay/root/criu-loop.sh | 15 +++ 4 files changed, 145 insertions(+) create mode 100644 support/testing/tests/package/test_criu.py create mode 100644 support/testing/tests/package/test_criu/linux-criu.fragment create mode 100755 support/testing/tests/package/test_criu/rootfs-overlay/root/criu-loop.sh