diff mbox

[3/5] support/testing: add fs tests

Message ID 1486467363-19881-4-git-send-email-thomas.petazzoni@free-electrons.com
State Superseded
Headers show

Commit Message

Thomas Petazzoni Feb. 7, 2017, 11:36 a.m. UTC
This commit adds a number of test cases for various filesystem formats:
ext2/3/4, iso9660, jffs2, squashfs, ubi/ubifs and yaffs2. All of them
except yaffs2 are runtime tested. The iso9660 set of test cases is
particularly rich, testing the proper operation of the iso9660 support
with all of grub, grub2 and isolinux.

Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
 support/testing/conf/grub-menu.lst                 |  20 +++
 support/testing/conf/grub2.cfg                     |   7 +
 support/testing/conf/isolinux.cfg                  |   5 +
 .../testing/conf/minimal-x86-qemu-kernel.config    |  23 +++
 support/testing/tests/fs/__init__.py               |   0
 support/testing/tests/fs/test_ext.py               | 119 +++++++++++++++
 support/testing/tests/fs/test_iso9660.py           | 161 +++++++++++++++++++++
 support/testing/tests/fs/test_jffs2.py             |  45 ++++++
 support/testing/tests/fs/test_squashfs.py          |  37 +++++
 support/testing/tests/fs/test_ubi.py               |  39 +++++
 support/testing/tests/fs/test_yaffs2.py            |  12 ++
 11 files changed, 468 insertions(+)
 create mode 100644 support/testing/conf/grub-menu.lst
 create mode 100644 support/testing/conf/grub2.cfg
 create mode 100644 support/testing/conf/isolinux.cfg
 create mode 100644 support/testing/conf/minimal-x86-qemu-kernel.config
 create mode 100644 support/testing/tests/fs/__init__.py
 create mode 100644 support/testing/tests/fs/test_ext.py
 create mode 100644 support/testing/tests/fs/test_iso9660.py
 create mode 100644 support/testing/tests/fs/test_jffs2.py
 create mode 100644 support/testing/tests/fs/test_squashfs.py
 create mode 100644 support/testing/tests/fs/test_ubi.py
 create mode 100644 support/testing/tests/fs/test_yaffs2.py

Comments

Ricardo Martincoski March 2, 2017, 1:51 a.m. UTC | #1
Thomas,

On Tue, Feb 07, 2017 at 09:36 AM, Thomas Petazzoni wrote:

[snip]
> +++ b/support/testing/conf/minimal-x86-qemu-kernel.config
[snip]

I observed sometimes a testcase fails when it shouldn't.

This emulated system displays some time after boot this message:
Switched to clocksource tsc

When the testcase is small there is a chance the message arrives when 'echo $?'
is being issued.

I took a look at the kernel and I didn't find compile-time configs to avoid
this message.
There are some options for bootargs that maybe could help:
 clocksource=tsc
 loglevel=0
 quiet
But qemu can only use -append when -kernel is used too.

The only config I found that could workaround the error is
# CONFIG_PRINTK is not set
of course it is a big change, and it would need CONFIG_EXPERT=y and it would
also change few more lines in the defconfig.

But I will be happy with any other solution.


Here is how I reproduce the error, but I think its occurrence will depend a lot
on the host machine.

running (after fixing the arch in emulator and also changing the expected
return code to 0):
$ for i in $(seq 1 100); do echo $i ; support/testing/run-tests -d dl \
  -o $(readlink -f output) -k tests.fs.test_iso9660.TestIso9660GrubInternal \
  || break; done

eventually leads to:
======================================================================
ERROR: test_run (tests.fs.test_iso9660.TestIso9660GrubInternal)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/testing-v1/support/testing/tests/fs/test_iso9660.py", line 120, in test_run
    exit_code = test_touch_file(self.emulator)
  File "/tmp/testing-v1/support/testing/tests/fs/test_iso9660.py", line 41, in test_touch_file
    _, exit_code = emulator.run("touch test")
  File "/tmp/testing-v1/support/testing/infra/emulator.py", line 131, in run
    exit_code = int(exit_code)
ValueError: invalid literal for int() with base 10: 'echo $?'

----------------------------------------------------------------------
Ran 1 test in 2.789s

log when the test is OK (most of times)
---
mount | grep 'rootfs on / type rootfs'
rootfs on / type rootfs (rw)
# echo $?
0
# > command terminated, status 0
 > running 'touch test'
touch test
# echo $?
0
# > command terminated, status 0
---

log when the test FAILS
---
rootfs on / type rootfs (rw)
# echo $?
0
# > command terminated, status 0
 > running 'touch test'
touch test
# Switched to clocksource tsc
echo $?
0
#
---

[snip]
> +++ b/support/testing/tests/fs/test_iso9660.py
[snip]
> +    emulator.boot(arch="i386", options=["-cdrom", img])

See my comment in patch 1.

[snip]
> +def test_touch_file(emulator):
> +    _, exit_code = emulator.run("touch test")
> +    return exit_code
[snip]
> +class TestIso9660Grub2Internal(infra.basetest.BRTest):
[snip]
> +        exit_code = test_touch_file(self.emulator)
> +        self.assertEqual(exit_code, 1)

Same comment as in TestIso9660SyslinuxInternal below.

> +
> +class TestIso9660GrubInternal(infra.basetest.BRTest):
[snip]
> +        exit_code = test_touch_file(self.emulator)
> +        self.assertEqual(exit_code, 1)

Same comment as in TestIso9660SyslinuxInternal below.

[snip]
> +class TestIso9660SyslinuxExternal(infra.basetest.BRTest):
[snip]
> +        exit_code = test_touch_file(self.emulator)
> +        self.assertEqual(exit_code, 1)
> +
> +class TestIso9660SyslinuxInternal(infra.basetest.BRTest):
[snip]
> +        exit_code = test_touch_file(self.emulator)
> +        self.assertEqual(exit_code, 1)

This testcase fails for me like this (after fixing arch in emulator):
======================================================================
FAIL: test_run (tests.fs.test_iso9660.TestIso9660SyslinuxInternal)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/testing-v1/support/testing/tests/fs/test_iso9660.py", line 161, in test_run
    self.assertEqual(exit_code, 1)
AssertionError: 0 != 1

I am not sure if in this case the rootfs should be read-only or not, but this
differs from your previous iteration:

    def run_external(self):
[snip]
        (r, s) = self.s.run("touch test")
        self.assertEqual(s, 1)

    def run_internal(self):
[snip]
        (r, s) = self.s.run("touch test")
        self.assertEqual(s, 0)

Regards,
Ricardo
Thomas Petazzoni March 5, 2017, 2:13 p.m. UTC | #2
Hello,

On Wed, 01 Mar 2017 22:51:31 -0300, Ricardo Martincoski wrote:

> I observed sometimes a testcase fails when it shouldn't.
> 
> This emulated system displays some time after boot this message:
> Switched to clocksource tsc
> 
> When the testcase is small there is a chance the message arrives when 'echo $?'
> is being issued.
> 
> I took a look at the kernel and I didn't find compile-time configs to avoid
> this message.
> There are some options for bootargs that maybe could help:
>  clocksource=tsc
>  loglevel=0
>  quiet
> But qemu can only use -append when -kernel is used too.
> 
> The only config I found that could workaround the error is
> # CONFIG_PRINTK is not set
> of course it is a big change, and it would need CONFIG_EXPERT=y and it would
> also change few more lines in the defconfig.
> 
> But I will be happy with any other solution.

Thanks for having debugged this issue! I was unable to reproduce on my
side, even for a 100 iterations loop. However, I've fixed it by running
"dmesg -n 1" as the first command after log in. This tells the kernel
to only display emergency kernel messages to the console, while the
"Switching to clocksource tsc" message has the info level, which is a
lower priority.

> I am not sure if in this case the rootfs should be read-only or not, but this
> differs from your previous iteration:

That's a mistake that was introduced while refactoring/cleaning up the
whole thing. Indeed in the "internal" case, we're running in an
initramfs, so the rootfs is read/write, and the "touch" is expected to
succeed.

Fixed as well, thanks!

Thomas
diff mbox

Patch

diff --git a/support/testing/conf/grub-menu.lst b/support/testing/conf/grub-menu.lst
new file mode 100644
index 0000000..6143d80
--- /dev/null
+++ b/support/testing/conf/grub-menu.lst
@@ -0,0 +1,20 @@ 
+default		0
+timeout		1
+
+# Used when no splashimage is used
+color 		cyan/blue white/blue
+
+# Gets enabled/disabled depending on Grub support for splashimage
+splashimage	/boot/grub/splash.xpm.gz
+
+# Used when a splashimage is enabled
+foreground 	000000
+background 	cccccc
+
+title		Buildroot ISO9660 image
+kernel		__KERNEL_PATH__ root=/dev/sr0 console=ttyS0,115200
+initrd		__INITRD_PATH__
+
+title		Hard Drive (first partition)
+rootnoverify	(hd0)
+chainloader	+1
diff --git a/support/testing/conf/grub2.cfg b/support/testing/conf/grub2.cfg
new file mode 100644
index 0000000..a982d0b
--- /dev/null
+++ b/support/testing/conf/grub2.cfg
@@ -0,0 +1,7 @@ 
+set default="0"
+set timeout="1"
+
+menuentry "Buildroot" {
+	linux __KERNEL_PATH__ root=/dev/sr0 console=ttyS0,115200
+	initrd __INITRD_PATH__
+}
diff --git a/support/testing/conf/isolinux.cfg b/support/testing/conf/isolinux.cfg
new file mode 100644
index 0000000..ba031a6
--- /dev/null
+++ b/support/testing/conf/isolinux.cfg
@@ -0,0 +1,5 @@ 
+default 1
+label 1
+      kernel __KERNEL_PATH__
+      initrd __INITRD_PATH__
+      append root=/dev/sr0 console=ttyS0,115200
diff --git a/support/testing/conf/minimal-x86-qemu-kernel.config b/support/testing/conf/minimal-x86-qemu-kernel.config
new file mode 100644
index 0000000..8f6ceef
--- /dev/null
+++ b/support/testing/conf/minimal-x86-qemu-kernel.config
@@ -0,0 +1,23 @@ 
+# CONFIG_64BIT is not set
+CONFIG_SYSVIPC=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_SUSPEND is not set
+# CONFIG_ACPI is not set
+CONFIG_CPU_IDLE=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_ATA=y
+CONFIG_ATA_PIIX=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_THERMAL=y
+CONFIG_EXT4_FS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_VIRTUALIZATION is not set
diff --git a/support/testing/tests/fs/__init__.py b/support/testing/tests/fs/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/support/testing/tests/fs/test_ext.py b/support/testing/tests/fs/test_ext.py
new file mode 100644
index 0000000..f7e2e85
--- /dev/null
+++ b/support/testing/tests/fs/test_ext.py
@@ -0,0 +1,119 @@ 
+import os
+import subprocess
+
+import infra.basetest
+
+VOLNAME_PROP = "Filesystem volume name"
+REVISION_PROP = "Filesystem revision #"
+FEATURES_PROP = "Filesystem features"
+BLOCKCNT_PROP = "Block count"
+INODECNT_PROP = "Inode count"
+RESBLKCNT_PROP = "Reserved block count"
+
+CHECK_FS_TYPE_CMD = "mount | grep '/dev/root on / type {}'"
+
+def dumpe2fs_run(builddir, image):
+    cmd = ["host/usr/sbin/dumpe2fs", os.path.join("images", image)]
+    ret = subprocess.check_output(cmd,
+                                  stderr=open(os.devnull, "w"),
+                                  cwd=builddir,
+                                  env={"LANG": "C"})
+    return ret.strip().splitlines()
+
+def dumpe2fs_getprop(out, prop):
+    for lines in out:
+        lines = lines.split(": ")
+        if lines[0] == prop:
+            return lines[1].strip()
+
+def boot_img_and_check_fs_type(emulator, builddir, fs_type):
+    img = os.path.join(builddir, "images", "rootfs.{}".format(fs_type))
+    emulator.boot(arch="armv7",
+                  kernel="builtin",
+                  kernel_cmdline=["root=/dev/mmcblk0",
+                                  "rootfstype={}".format(fs_type)],
+                  options=["-drive", "file={},if=sd".format(img)])
+    emulator.login()
+    _, exit_code = emulator.run(CHECK_FS_TYPE_CMD.format(fs_type))
+    return exit_code
+
+class TestExt2(infra.basetest.BRTest):
+    config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
+"""
+BR2_TARGET_ROOTFS_EXT2=y
+BR2_TARGET_ROOTFS_EXT2_2r0=y
+BR2_TARGET_ROOTFS_EXT2_LABEL="foobaz"
+# BR2_TARGET_ROOTFS_TAR is not set
+"""
+
+    def test_run(self):
+        out = dumpe2fs_run(self.builddir, "rootfs.ext2")
+        self.assertEqual(dumpe2fs_getprop(out, VOLNAME_PROP), "foobaz")
+        self.assertEqual(dumpe2fs_getprop(out, REVISION_PROP), "0 (original)")
+
+        exit_code = boot_img_and_check_fs_type(self.emulator,
+                                               self.builddir, "ext2")
+        self.assertEqual(exit_code, 0)
+
+class TestExt2r1(infra.basetest.BRTest):
+    config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
+"""
+BR2_TARGET_ROOTFS_EXT2=y
+BR2_TARGET_ROOTFS_EXT2_2r1=y
+BR2_TARGET_ROOTFS_EXT2_LABEL="foobar"
+# BR2_TARGET_ROOTFS_TAR is not set
+"""
+
+    def test_run(self):
+        out = dumpe2fs_run(self.builddir, "rootfs.ext2")
+        self.assertEqual(dumpe2fs_getprop(out, VOLNAME_PROP), "foobar")
+        self.assertEqual(dumpe2fs_getprop(out, REVISION_PROP), "1 (dynamic)")
+        self.assertNotIn("has_journal", dumpe2fs_getprop(out, FEATURES_PROP))
+
+        exit_code = boot_img_and_check_fs_type(self.emulator,
+                                               self.builddir, "ext2")
+        self.assertEqual(exit_code, 0)
+
+class TestExt3(infra.basetest.BRTest):
+    config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
+"""
+BR2_TARGET_ROOTFS_EXT2=y
+BR2_TARGET_ROOTFS_EXT2_3=y
+# BR2_TARGET_ROOTFS_TAR is not set
+"""
+
+    def test_run(self):
+        out = dumpe2fs_run(self.builddir, "rootfs.ext3")
+        self.assertEqual(dumpe2fs_getprop(out, REVISION_PROP), "1 (dynamic)")
+        self.assertIn("has_journal", dumpe2fs_getprop(out, FEATURES_PROP))
+
+        exit_code = boot_img_and_check_fs_type(self.emulator,
+                                               self.builddir, "ext3")
+        self.assertEqual(exit_code, 0)
+
+class TestExt4(infra.basetest.BRTest):
+    config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
+"""
+BR2_TARGET_ROOTFS_EXT2=y
+BR2_TARGET_ROOTFS_EXT2_4=y
+BR2_TARGET_ROOTFS_EXT2_BLOCKS=16384
+BR2_TARGET_ROOTFS_EXT2_INODES=3000
+BR2_TARGET_ROOTFS_EXT2_RESBLKS=10
+# BR2_TARGET_ROOTFS_TAR is not set
+"""
+
+    def test_run(self):
+        out = dumpe2fs_run(self.builddir, "rootfs.ext4")
+        self.assertEqual(dumpe2fs_getprop(out, REVISION_PROP), "1 (dynamic)")
+        self.assertEqual(dumpe2fs_getprop(out, BLOCKCNT_PROP), "16384")
+        # Yes there are 8 more inodes than requested
+        self.assertEqual(dumpe2fs_getprop(out, INODECNT_PROP), "3008")
+        self.assertEqual(dumpe2fs_getprop(out, RESBLKCNT_PROP), "1638")
+        self.assertIn("has_journal", dumpe2fs_getprop(out, FEATURES_PROP))
+        self.assertIn("extent", dumpe2fs_getprop(out, FEATURES_PROP))
+
+        exit_code = boot_img_and_check_fs_type(self.emulator,
+                                               self.builddir, "ext4")
+        self.assertEqual(exit_code, 0)
+
+
diff --git a/support/testing/tests/fs/test_iso9660.py b/support/testing/tests/fs/test_iso9660.py
new file mode 100644
index 0000000..b56ff07
--- /dev/null
+++ b/support/testing/tests/fs/test_iso9660.py
@@ -0,0 +1,161 @@ 
+import os
+
+import infra.basetest
+
+BASIC_CONFIG = \
+"""
+BR2_x86_pentium4=y
+BR2_TOOLCHAIN_EXTERNAL=y
+BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y
+BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD=y
+BR2_TOOLCHAIN_EXTERNAL_URL="http://autobuild.buildroot.org/toolchains/tarballs/br-i386-pentium4-full-2015.05-496-g85945aa.tar.bz2"
+BR2_TOOLCHAIN_EXTERNAL_GCC_4_9=y
+BR2_TOOLCHAIN_EXTERNAL_HEADERS_3_2=y
+BR2_TOOLCHAIN_EXTERNAL_LOCALE=y
+# BR2_TOOLCHAIN_EXTERNAL_HAS_THREADS_DEBUG is not set
+BR2_TOOLCHAIN_EXTERNAL_INET_RPC=y
+BR2_TOOLCHAIN_EXTERNAL_CXX=y
+BR2_TARGET_GENERIC_GETTY_PORT="ttyS0"
+BR2_TARGET_GENERIC_GETTY_BAUDRATE_115200=y
+BR2_LINUX_KERNEL=y
+BR2_LINUX_KERNEL_CUSTOM_VERSION=y
+BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="4.0"
+BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
+BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="{}"
+# BR2_TARGET_ROOTFS_TAR is not set
+""".format(infra.filepath("conf/minimal-x86-qemu-kernel.config"))
+
+def test_mount_internal_external(emulator, builddir, internal=True):
+    img = os.path.join(builddir, "images", "rootfs.iso9660")
+    emulator.boot(arch="i386", options=["-cdrom", img])
+    emulator.login()
+
+    cmd = "mount | grep '/dev/root on / type iso9660'"
+    if internal:
+        cmd = "mount | grep 'rootfs on / type rootfs'"
+
+    _, exit_code = emulator.run(cmd)
+    return exit_code
+
+def test_touch_file(emulator):
+    _, exit_code = emulator.run("touch test")
+    return exit_code
+
+#
+# Grub 2
+#
+
+class TestIso9660Grub2External(infra.basetest.BRTest):
+    config = BASIC_CONFIG + \
+"""
+BR2_TARGET_ROOTFS_ISO9660=y
+# BR2_TARGET_ROOTFS_ISO9660_INITRD is not set
+BR2_TARGET_GRUB2=y
+BR2_TARGET_GRUB2_BOOT_PARTITION="cd"
+BR2_TARGET_GRUB2_BUILTIN_MODULES="boot linux ext2 fat part_msdos part_gpt normal biosdisk iso9660"
+BR2_TARGET_ROOTFS_ISO9660_BOOT_MENU="{}"
+""".format(infra.filepath("conf/grub2.cfg"))
+
+    def test_run(self):
+        exit_code = test_mount_internal_external(self.emulator,
+                                                 self.builddir, internal=False)
+        self.assertEqual(exit_code, 0)
+
+        exit_code = test_touch_file(self.emulator)
+        self.assertEqual(exit_code, 1)
+
+class TestIso9660Grub2Internal(infra.basetest.BRTest):
+    config = BASIC_CONFIG + \
+"""
+BR2_TARGET_ROOTFS_ISO9660=y
+BR2_TARGET_ROOTFS_ISO9660_INITRD=y
+BR2_TARGET_GRUB2=y
+BR2_TARGET_GRUB2_BOOT_PARTITION="cd"
+BR2_TARGET_GRUB2_BUILTIN_MODULES="boot linux ext2 fat part_msdos part_gpt normal biosdisk iso9660"
+BR2_TARGET_ROOTFS_ISO9660_BOOT_MENU="{}"
+""".format(infra.filepath("conf/grub2.cfg"))
+
+    def test_run(self):
+        exit_code = test_mount_internal_external(self.emulator,
+                                                 self.builddir, internal=True)
+        self.assertEqual(exit_code, 0)
+
+        exit_code = test_touch_file(self.emulator)
+        self.assertEqual(exit_code, 1)
+
+#
+# Grub
+#
+
+class TestIso9660GrubExternal(infra.basetest.BRTest):
+    config = BASIC_CONFIG + \
+"""
+BR2_TARGET_ROOTFS_ISO9660=y
+# BR2_TARGET_ROOTFS_ISO9660_INITRD is not set
+BR2_TARGET_GRUB=y
+BR2_TARGET_ROOTFS_ISO9660_BOOT_MENU="{}"
+""".format(infra.filepath("conf/grub-menu.lst"))
+
+    def test_run(self):
+        exit_code = test_mount_internal_external(self.emulator,
+                                                 self.builddir, internal=False)
+        self.assertEqual(exit_code, 0)
+
+        exit_code = test_touch_file(self.emulator)
+        self.assertEqual(exit_code, 1)
+
+class TestIso9660GrubInternal(infra.basetest.BRTest):
+    config = BASIC_CONFIG + \
+"""
+BR2_TARGET_ROOTFS_ISO9660=y
+BR2_TARGET_GRUB=y
+BR2_TARGET_ROOTFS_ISO9660_BOOT_MENU="{}"
+""".format(infra.filepath("conf/grub-menu.lst"))
+
+    def test_run(self):
+        exit_code = test_mount_internal_external(self.emulator,
+                                                 self.builddir, internal=True)
+        self.assertEqual(exit_code, 0)
+
+        exit_code = test_touch_file(self.emulator)
+        self.assertEqual(exit_code, 1)
+
+#
+# Syslinux
+#
+
+class TestIso9660SyslinuxExternal(infra.basetest.BRTest):
+    config = BASIC_CONFIG + \
+"""
+BR2_TARGET_ROOTFS_ISO9660=y
+# BR2_TARGET_ROOTFS_ISO9660_INITRD is not set
+BR2_TARGET_ROOTFS_ISO9660_HYBRID=y
+BR2_TARGET_ROOTFS_ISO9660_BOOT_MENU="{}"
+BR2_TARGET_SYSLINUX=y
+""".format(infra.filepath("conf/isolinux.cfg"))
+
+    def test_run(self):
+        exit_code = test_mount_internal_external(self.emulator,
+                                                 self.builddir, internal=False)
+        self.assertEqual(exit_code, 0)
+
+        exit_code = test_touch_file(self.emulator)
+        self.assertEqual(exit_code, 1)
+
+class TestIso9660SyslinuxInternal(infra.basetest.BRTest):
+    config = BASIC_CONFIG + \
+"""
+BR2_TARGET_ROOTFS_ISO9660=y
+BR2_TARGET_ROOTFS_ISO9660_INITRD=y
+BR2_TARGET_ROOTFS_ISO9660_HYBRID=y
+BR2_TARGET_ROOTFS_ISO9660_BOOT_MENU="{}"
+BR2_TARGET_SYSLINUX=y
+""".format(infra.filepath("conf/isolinux.cfg"))
+
+    def test_run(self):
+        exit_code = test_mount_internal_external(self.emulator,
+                                                 self.builddir, internal=True)
+        self.assertEqual(exit_code, 0)
+
+        exit_code = test_touch_file(self.emulator)
+        self.assertEqual(exit_code, 1)
diff --git a/support/testing/tests/fs/test_jffs2.py b/support/testing/tests/fs/test_jffs2.py
new file mode 100644
index 0000000..0d45af2
--- /dev/null
+++ b/support/testing/tests/fs/test_jffs2.py
@@ -0,0 +1,45 @@ 
+import os
+import subprocess
+
+import infra.basetest
+
+def jffs2dump_find_file(files_list, fname):
+    for file_name in files_list:
+        file_name = file_name.strip()
+        if file_name.startswith("Dirent") and file_name.endswith(fname):
+            return True
+    return False
+
+class TestJffs2(infra.basetest.BRTest):
+    config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
+"""
+BR2_TARGET_ROOTFS_JFFS2=y
+BR2_TARGET_ROOTFS_JFFS2_CUSTOM=y
+BR2_TARGET_ROOTFS_JFFS2_CUSTOM_EBSIZE=0x80000
+BR2_TARGET_ROOTFS_JFFS2_NOCLEANMARKER=y
+BR2_TARGET_ROOTFS_JFFS2_PAD=y
+BR2_TARGET_ROOTFS_JFFS2_PADSIZE=0x4000000
+# BR2_TARGET_ROOTFS_TAR is not set
+"""
+
+    # TODO: there are some scary JFFS2 messages when one starts to
+    # write files in the rootfs: "jffs2: Newly-erased block contained
+    # word 0x0 at offset 0x046c0000". To be investigated.
+
+    def test_run(self):
+        img = os.path.join(self.builddir, "images", "rootfs.jffs2")
+        out = subprocess.check_output(["host/usr/sbin/jffs2dump", "-c", img],
+                                      cwd=self.builddir,
+                                      env={"LANG": "C"})
+        out = out.splitlines()
+        self.assertTrue(jffs2dump_find_file(out, "busybox"))
+
+        self.emulator.boot(arch="armv7",
+                           kernel="builtin",
+                           kernel_cmdline=["root=/dev/mtdblock0",
+                                           "rootfstype=jffs2"],
+                           options=["-drive", "file={},if=pflash".format(img)])
+        self.emulator.login()
+        cmd = "mount | grep '/dev/root on / type jffs2'"
+        _, exit_code = self.emulator.run(cmd)
+        self.assertEqual(exit_code, 0)
diff --git a/support/testing/tests/fs/test_squashfs.py b/support/testing/tests/fs/test_squashfs.py
new file mode 100644
index 0000000..edaa087
--- /dev/null
+++ b/support/testing/tests/fs/test_squashfs.py
@@ -0,0 +1,37 @@ 
+import os
+import subprocess
+
+import infra.basetest
+
+class TestSquashfs(infra.basetest.BRTest):
+    config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
+"""
+BR2_TARGET_ROOTFS_SQUASHFS=y
+# BR2_TARGET_ROOTFS_SQUASHFS4_GZIP is not set
+BR2_TARGET_ROOTFS_SQUASHFS4_LZ4=y
+# BR2_TARGET_ROOTFS_TAR is not set
+"""
+
+    def test_run(self):
+        unsquashfs_cmd = ["host/usr/bin/unsquashfs", "-s", "images/rootfs.squashfs"]
+        out = subprocess.check_output(unsquashfs_cmd,
+                                      cwd=self.builddir,
+                                      env={"LANG": "C"})
+        out = out.splitlines()
+        self.assertEqual(out[0],
+                         "Found a valid SQUASHFS 4:0 superblock on images/rootfs.squashfs.")
+        self.assertEqual(out[3], "Compression lz4")
+
+        img = os.path.join(self.builddir, "images", "rootfs.squashfs")
+        subprocess.call(["truncate", "-s", "%1M", img])
+
+        self.emulator.boot(arch="armv7",
+                           kernel="builtin",
+                           kernel_cmdline=["root=/dev/mmcblk0",
+                                           "rootfstype=squashfs"],
+                           options=["-drive", "file={},if=sd,format=raw".format(img)])
+        self.emulator.login()
+
+        cmd = "mount | grep '/dev/root on / type squashfs'"
+        _, exit_code = self.emulator.run(cmd)
+        self.assertEqual(exit_code, 0)
diff --git a/support/testing/tests/fs/test_ubi.py b/support/testing/tests/fs/test_ubi.py
new file mode 100644
index 0000000..ede4999
--- /dev/null
+++ b/support/testing/tests/fs/test_ubi.py
@@ -0,0 +1,39 @@ 
+import subprocess
+import os
+
+import infra.basetest
+
+class TestUbi(infra.basetest.BRTest):
+    config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
+"""
+BR2_TARGET_ROOTFS_UBIFS=y
+BR2_TARGET_ROOTFS_UBIFS_LEBSIZE=0x7ff80
+BR2_TARGET_ROOTFS_UBIFS_MINIOSIZE=0x1
+BR2_TARGET_ROOTFS_UBI=y
+BR2_TARGET_ROOTFS_UBI_PEBSIZE=0x80000
+BR2_TARGET_ROOTFS_UBI_SUBSIZE=1
+"""
+
+    # TODO: if you boot Qemu twice on the same UBI image, it fails to
+    # attach the image the second time, with "ubi0 error:
+    # ubi_read_volume_table: the layout volume was not found".
+    # To be investigated.
+    def test_run(self):
+        img = os.path.join(self.builddir, "images", "rootfs.ubi")
+        out = subprocess.check_output(["file", img],
+                                      cwd=self.builddir,
+                                      env={"LANG": "C"})
+        out = out.splitlines()
+
+        subprocess.call(["truncate", "-s 128M", img])
+
+        self.emulator.boot(arch="armv7",
+                           kernel="builtin",
+                           kernel_cmdline=["root=ubi0:rootfs",
+                                           "ubi.mtd=0",
+                                           "rootfstype=ubifs"],
+                           options=["-drive", "file={},if=pflash".format(img)])
+        self.emulator.login()
+        cmd = "mount | grep 'ubi0:rootfs on / type ubifs'"
+        _, exit_code = self.emulator.run(cmd)
+        self.assertEqual(exit_code, 0)
diff --git a/support/testing/tests/fs/test_yaffs2.py b/support/testing/tests/fs/test_yaffs2.py
new file mode 100644
index 0000000..0ffb758
--- /dev/null
+++ b/support/testing/tests/fs/test_yaffs2.py
@@ -0,0 +1,12 @@ 
+import os
+
+import infra.basetest
+
+class TestYaffs2(infra.basetest.BRTest):
+    config = infra.basetest.BASIC_TOOLCHAIN_CONFIG + \
+            infra.basetest.MINIMAL_CONFIG + \
+            "BR2_TARGET_ROOTFS_YAFFS2=y"
+
+    def test_run(self):
+        img = os.path.join(self.builddir, "images", "rootfs.yaffs2")
+        self.assertTrue(os.path.exists(img))