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

Submitted by Thomas Petazzoni on March 20, 2017, 8:36 p.m.

Details

Message ID 1490042214-6762-4-git-send-email-thomas.petazzoni@free-electrons.com
State Accepted
Headers show

Commit Message

Thomas Petazzoni March 20, 2017, 8:36 p.m.
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           | 162 +++++++++++++++++++++
 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, 469 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

Luca Ceresoli May 7, 2017, 8:55 p.m.
Hi,

this the review I had written a few days ago. Since the patch has just
been applied, I've reworded it as a list of proposed improvements and
request for clarifications.

On 20/03/2017 21:36, Thomas Petazzoni wrote:
> 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           | 162 +++++++++++++++++++++
>  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, 469 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

I suspect it's already been suggested, but I would rather put these
files in the 'fs' subdirectory, unless we expect to use them for non-fs
tests.

Do other people agree? Should I send a patch?

> 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
[...]
> +def dumpe2fs_getprop(out, prop):
> +    for lines in out:

Here 'lines' is set to a string (one line)...

> +        lines = lines.split(": ")

...and here it is reassigned to a list (the line fields, as they are
called in awk. Or is the second assignment of 'lines' creating a new
variable with the same name? Whether the reply, I don't like this.

> +        if lines[0] == prop:
> +            return lines[1].strip()

My proposal (tested):

def dumpe2fs_getprop(out, prop):
    for line in out:
        fields = line.split(": ")
        if fields[0] == prop:
            return fields[1].strip()

Unless there's a good reason to keep the code as is, I'll send a patch
anyway, to improve readability at least.

> +def boot_img_and_check_fs_type(emulator, builddir, fs_type):
> +    img = os.path.join(builddir, "images", "rootfs.{}".format(fs_type))

Here (and similarly in several other places) this looks a lot more
intuitive and concise to me:

  "rootfs." + fs_type

Any good reason the initial form is preferred? Pythonists out there?

[...]

> +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))

It would be nice to have both positive and a negative test for each
tested item. Specifically, I'd add self.assertIn("extent", ...) for ext3.

I'll send a patch for this.

> diff --git a/support/testing/tests/fs/test_iso9660.py b/support/testing/tests/fs/test_iso9660.py
> new file mode 100644
> index 0000000..eec6e89
> --- /dev/null
> +++ b/support/testing/tests/fs/test_iso9660.py

[...]

> +#
> +# Syslinux
> +#
> +
> +class TestIso9660SyslinuxExternal(infra.basetest.BRTest):

The two syslinux tests are failing on top of current master. This is
since commit 6e432d5ecb46 ("syslinux: build with the target toolchain").

The error message is:

  .../i686-linux-ld: unrecognized option '--no-dynamic-linker'

> 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
[...]
> +    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])

Why do we need this call to truncate?

Patch hide | download patch | download mbox

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..eec6e89
--- /dev/null
+++ b/support/testing/tests/fs/test_iso9660.py
@@ -0,0 +1,162 @@ 
+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()
+
+    if internal:
+        cmd = "mount | grep 'rootfs on / type rootfs'"
+    else:
+        cmd = "mount | grep '/dev/root on / type iso9660'"
+
+    _, 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, 0)
+
+#
+# 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, 0)
+
+#
+# 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, 0)
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))