support/testing: add fs tests

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>
This commit is contained in:
Thomas Petazzoni 2017-03-20 21:36:52 +01:00
parent 96e21b617d
commit bf4a6490e4
11 changed files with 469 additions and 0 deletions

View File

@ -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

View File

@ -0,0 +1,7 @@
set default="0"
set timeout="1"
menuentry "Buildroot" {
linux __KERNEL_PATH__ root=/dev/sr0 console=ttyS0,115200
initrd __INITRD_PATH__
}

View File

@ -0,0 +1,5 @@
default 1
label 1
kernel __KERNEL_PATH__
initrd __INITRD_PATH__
append root=/dev/sr0 console=ttyS0,115200

View File

@ -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

View File

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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