summaryrefslogtreecommitdiffstats
path: root/testsuite
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:03:56 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:03:56 +0000
commit18da3ffcd7f3c8a0c5f790c801b5813503c2273d (patch)
tree84caf98dc5cef3d123c56ba12e35fd67026e0693 /testsuite
parentInitial commit. (diff)
downloadkmod-18da3ffcd7f3c8a0c5f790c801b5813503c2273d.tar.xz
kmod-18da3ffcd7f3c8a0c5f790c801b5813503c2273d.zip
Adding upstream version 31+20240202.upstream/31+20240202
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testsuite')
-rw-r--r--testsuite/.gitignore57
-rw-r--r--testsuite/COPYING504
-rw-r--r--testsuite/Makefile15
-rw-r--r--testsuite/README61
-rw-r--r--testsuite/delete_module.c168
-rw-r--r--testsuite/init_module.c403
-rw-r--r--testsuite/module-playground/.gitignore16
-rw-r--r--testsuite/module-playground/Makefile83
-rw-r--r--testsuite/module-playground/Makefile.arch14
-rw-r--r--testsuite/module-playground/README26
-rw-r--r--testsuite/module-playground/cache/mod-fake-cciss.kobin0 -> 5504 bytes
-rw-r--r--testsuite/module-playground/cache/mod-fake-hpsa.kobin0 -> 5264 bytes
-rw-r--r--testsuite/module-playground/cache/mod-fake-scsi-mod.kobin0 -> 4328 bytes
-rw-r--r--testsuite/module-playground/cache/mod-foo-a.kobin0 -> 4392 bytes
-rw-r--r--testsuite/module-playground/cache/mod-foo-b.kobin0 -> 4392 bytes
-rw-r--r--testsuite/module-playground/cache/mod-foo-c.kobin0 -> 4392 bytes
-rw-r--r--testsuite/module-playground/cache/mod-foo.kobin0 -> 3296 bytes
-rw-r--r--testsuite/module-playground/cache/mod-loop-a.kobin0 -> 4672 bytes
-rw-r--r--testsuite/module-playground/cache/mod-loop-b.kobin0 -> 4672 bytes
-rw-r--r--testsuite/module-playground/cache/mod-loop-c.kobin0 -> 4672 bytes
-rw-r--r--testsuite/module-playground/cache/mod-loop-d.kobin0 -> 4672 bytes
-rw-r--r--testsuite/module-playground/cache/mod-loop-e.kobin0 -> 4672 bytes
-rw-r--r--testsuite/module-playground/cache/mod-loop-f.kobin0 -> 194112 bytes
-rw-r--r--testsuite/module-playground/cache/mod-loop-g.kobin0 -> 194112 bytes
-rw-r--r--testsuite/module-playground/cache/mod-loop-h.kobin0 -> 197808 bytes
-rw-r--r--testsuite/module-playground/cache/mod-loop-i.kobin0 -> 197808 bytes
-rw-r--r--testsuite/module-playground/cache/mod-loop-j.kobin0 -> 197968 bytes
-rw-r--r--testsuite/module-playground/cache/mod-loop-k.kobin0 -> 197808 bytes
-rw-r--r--testsuite/module-playground/cache/mod-simple.kobin0 -> 3472 bytes
-rw-r--r--testsuite/module-playground/dummy.pkcs7bin0 -> 721 bytes
-rw-r--r--testsuite/module-playground/dummy.sha1bin0 -> 102411 bytes
-rw-r--r--testsuite/module-playground/dummy.sha256bin0 -> 102411 bytes
-rw-r--r--testsuite/module-playground/mod-fake-cciss.c37
-rw-r--r--testsuite/module-playground/mod-fake-hpsa.c36
-rw-r--r--testsuite/module-playground/mod-fake-scsi-mod.c21
-rw-r--r--testsuite/module-playground/mod-foo-a.c20
-rw-r--r--testsuite/module-playground/mod-foo-b.c20
-rw-r--r--testsuite/module-playground/mod-foo-c.c20
-rw-r--r--testsuite/module-playground/mod-foo.c23
-rw-r--r--testsuite/module-playground/mod-loop-a.c27
-rw-r--r--testsuite/module-playground/mod-loop-b.c27
-rw-r--r--testsuite/module-playground/mod-loop-c.c25
-rw-r--r--testsuite/module-playground/mod-loop-d.c25
-rw-r--r--testsuite/module-playground/mod-loop-e.c25
-rw-r--r--testsuite/module-playground/mod-loop-f.c24
-rw-r--r--testsuite/module-playground/mod-loop-g.c24
-rw-r--r--testsuite/module-playground/mod-loop-h.c25
-rw-r--r--testsuite/module-playground/mod-loop-i.c25
-rw-r--r--testsuite/module-playground/mod-loop-j.c26
-rw-r--r--testsuite/module-playground/mod-loop-k.c25
-rw-r--r--testsuite/module-playground/mod-loop.h13
-rw-r--r--testsuite/module-playground/mod-simple-i386.kobin0 -> 1988 bytes
-rw-r--r--testsuite/module-playground/mod-simple-sparc64.kobin0 -> 2927 bytes
-rw-r--r--testsuite/module-playground/mod-simple-x86_64.kobin0 -> 2768 bytes
-rw-r--r--testsuite/module-playground/mod-simple.c32
-rw-r--r--testsuite/path.c214
-rw-r--r--testsuite/rootfs-pristine/test-blacklist/etc/modprobe.d/modprobe.conf2
-rw-r--r--testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.builtin0
-rw-r--r--testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.builtin.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.dep4
-rw-r--r--testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.dep.binbin0 -> 244 bytes
-rw-r--r--testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.devname1
-rw-r--r--testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.order7
-rw-r--r--testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.symbols4
-rw-r--r--testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.symbols.binbin0 -> 102 bytes
-rw-r--r--testsuite/rootfs-pristine/test-depmod/detect-loop/correct.txt5
-rw-r--r--testsuite/rootfs-pristine/test-depmod/detect-loop/lib/modules/4.4.4/modules.order0
-rw-r--r--testsuite/rootfs-pristine/test-depmod/modules-order-compressed/lib/modules/4.4.4/correct-modules.alias37
-rw-r--r--testsuite/rootfs-pristine/test-depmod/modules-order-compressed/lib/modules/4.4.4/modules.builtin0
-rw-r--r--testsuite/rootfs-pristine/test-depmod/modules-order-compressed/lib/modules/4.4.4/modules.order7
-rw-r--r--testsuite/rootfs-pristine/test-depmod/modules-outdir/correct-modules.alias37
-rw-r--r--testsuite/rootfs-pristine/test-depmod/modules-outdir/correct-modules.dep3
-rw-r--r--testsuite/rootfs-pristine/test-depmod/modules-outdir/lib/modules/4.4.4/modules.builtin0
-rw-r--r--testsuite/rootfs-pristine/test-depmod/modules-outdir/lib/modules/4.4.4/modules.order7
-rw-r--r--testsuite/rootfs-pristine/test-depmod/search-order-external-first/etc/depmod.d/external.conf1
-rw-r--r--testsuite/rootfs-pristine/test-depmod/search-order-external-first/etc/depmod.d/search.conf1
-rw-r--r--testsuite/rootfs-pristine/test-depmod/search-order-external-first/lib/modules/4.4.4/correct-modules.dep1
-rw-r--r--testsuite/rootfs-pristine/test-depmod/search-order-external-last/etc/depmod.d/external.conf1
-rw-r--r--testsuite/rootfs-pristine/test-depmod/search-order-external-last/etc/depmod.d/search.conf1
-rw-r--r--testsuite/rootfs-pristine/test-depmod/search-order-external-last/lib/modules/4.4.4/correct-modules.dep1
-rw-r--r--testsuite/rootfs-pristine/test-depmod/search-order-override/etc/depmod.d/override.conf1
-rw-r--r--testsuite/rootfs-pristine/test-depmod/search-order-override/etc/depmod.d/search.conf1
-rw-r--r--testsuite/rootfs-pristine/test-depmod/search-order-override/lib/modules/4.4.4/correct-modules.dep1
-rw-r--r--testsuite/rootfs-pristine/test-depmod/search-order-same-prefix/etc/depmod.d/search.conf1
-rw-r--r--testsuite/rootfs-pristine/test-depmod/search-order-same-prefix/lib/modules/4.4.4/correct-modules.dep1
-rw-r--r--testsuite/rootfs-pristine/test-depmod/search-order-simple/etc/depmod.d/search.conf1
-rw-r--r--testsuite/rootfs-pristine/test-depmod/search-order-simple/lib/modules/4.4.4/correct-modules.dep1
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.builtin1
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.builtin.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.builtin.binbin0 -> 39 bytes
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.dep0
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.dep.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.devname1
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.symbols1
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.symbols.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.builtin1
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.builtin.binbin0 -> 39 bytes
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.dep0
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.dep.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.devname1
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.symbols1
-rw-r--r--testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.symbols.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.builtin1
-rw-r--r--testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.builtin.binbin0 -> 39 bytes
-rw-r--r--testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.dep0
-rw-r--r--testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.dep.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.devname1
-rw-r--r--testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.symbols1
-rw-r--r--testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.symbols.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-loaded/correct.txt2
-rw-r--r--testsuite/rootfs-pristine/test-loaded/proc/modules1
l---------testsuite/rootfs-pristine/test-loaded/sys/module/btusb/drivers/usb:btusb1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/holders/.gitignore0
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/initstate1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/notes/.note.gnu.build-idbin0 -> 36 bytes
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/disable_scofix1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/force_scofix1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/ignore_csr1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/ignore_dga1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/ignore_sniffer1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/reset1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/refcnt1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.bss1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.data1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.exit.text1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.gnu.linkonce.this_module1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.init.text1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.note.gnu.build-id1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.rodata1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.rodata.str1.11
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.rodata.str1.81
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.smp_locks1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.strtab1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.symtab1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.text1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/__param1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/srcversion1
-rw-r--r--testsuite/rootfs-pristine/test-loaded/sys/module/btusb/version1
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/correct-author.txt3
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/correct-depends.txt3
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/correct-description.txt0
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/correct-external.txt1
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/correct-filename.txt3
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/correct-license.txt4
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/correct-parm.txt0
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/correct-sig_hashalgo-openssl.txt3
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/correct-sig_hashalgo.txt4
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/correct-sig_key-openssl.txt3
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/correct-sig_key.txt3
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/correct-signer-openssl.txt3
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/correct-signer.txt3
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/correct.txt24
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.builtin.bin0
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.dep1
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.dep.binbin0 -> 73 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.devname0
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.symbols1
-rw-r--r--testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.symbols.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/alias-to-none/correct.txt0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/alias-to-none/etc/modprobe.d/bogus.conf1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.builtin.bin0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.dep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.dep.binbin0 -> 58 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.devname1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.symbols1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.symbols.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/alias-to-none/proc/modules0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/builtin/correct.txt1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.builtin1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.builtin.binbin0 -> 31 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.dep0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.dep.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.devname1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.softdep2
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.symbols1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.symbols.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.builtin.bin0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.dep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.dep.binbin0 -> 73 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.devname0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.symbols1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.symbols.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/external/proc/modules0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.builtin.bin0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.dep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.dep.binbin0 -> 58 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.devname1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.symbols1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.symbols.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/force/proc/modules0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/etc/modprobe.d/dumb-instal-loop.conf1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.builtin.bin0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.dep2
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.dep.binbin0 -> 118 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.devname1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.symbols3
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.symbols.binbin0 -> 78 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.builtin.bin0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.dep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.dep.binbin0 -> 73 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.devname0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.symbols1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.symbols.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-abspath/proc/modules0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.builtin.bin0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.dep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.dep.binbin0 -> 73 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.devname0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.symbols1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.symbols.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-from-relpath/proc/modules0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/correct.txt1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.builtin.bin0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.dep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.dep.binbin0 -> 58 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.devname1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.symbols1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.symbols.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/proc/cmdline1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/proc/modules0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline2/correct.txt5
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline2/proc/cmdline1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline3/correct.txt5
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline3/proc/cmdline1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline4/correct.txt4
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline4/proc/cmdline1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline5/correct.txt6
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline5/proc/cmdline1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline6/correct.txt6
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline6/proc/cmdline1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/correct.txt5
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/module-param-kcmdline7/correct.txt5
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/module-param-kcmdline7/proc/cmdline1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/proc/cmdline1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/correct.txt5
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/module-param-kcmdline7/correct.txt5
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/module-param-kcmdline7/proc/cmdline1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/proc/cmdline1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.builtin.bin0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.dep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.dep.binbin0 -> 58 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.devname1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.symbols1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.symbols.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel-force/proc/modules0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.builtin.bin0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.dep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.dep.binbin0 -> 58 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.devname1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.symbols1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.symbols.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/oldkernel/proc/modules0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/show-depends/correct-mod-simple.txt1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/show-depends/correct.txt2
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.builtin.bin0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.dep3
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.dep.binbin0 -> 188 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.devname1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.symbols3
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.symbols.binbin0 -> 78 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/show-depends/proc/modules2
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/show-depends/sys/module/mod_loop_a/initstate1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/show-depends/sys/module/mod_loop_b/initstate1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/show-exports/correct.txt1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/softdep-loop/etc/modprobe.d/dumb-softdep.conf1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.builtin.bin0
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.dep2
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.dep.binbin0 -> 118 bytes
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.devname1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.symbols3
-rw-r--r--testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.symbols.binbin0 -> 78 bytes
-rw-r--r--testsuite/rootfs-pristine/test-new-module/from_alias/correct.txt2
-rw-r--r--testsuite/rootfs-pristine/test-new-module/from_alias/etc/modprobe.d/modprobe.conf1
-rw-r--r--testsuite/rootfs-pristine/test-new-module/from_name/correct.txt6
-rw-r--r--testsuite/rootfs-pristine/test-rootfs/lib/modules/a1
-rw-r--r--testsuite/rootfs-pristine/test-rootfs/testdir/.gitignore0
-rw-r--r--testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.builtin0
-rw-r--r--testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.builtin.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.dep1
-rw-r--r--testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.dep.binbin0 -> 58 bytes
-rw-r--r--testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.devname1
-rw-r--r--testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.order0
-rw-r--r--testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.symbols1
-rw-r--r--testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.symbols.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.alias1
-rw-r--r--testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.alias.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.builtin0
-rw-r--r--testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.builtin.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.dep1
-rw-r--r--testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.dep.binbin0 -> 58 bytes
-rw-r--r--testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.devname1
-rw-r--r--testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.order0
-rw-r--r--testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.softdep1
-rw-r--r--testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.symbols1
-rw-r--r--testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.symbols.binbin0 -> 12 bytes
-rw-r--r--testsuite/rootfs-pristine/test-tools/remove/sys/module/mod_simple/holders/.gitignore0
-rw-r--r--testsuite/rootfs-pristine/test-tools/remove/sys/module/mod_simple/initstate1
-rw-r--r--testsuite/rootfs-pristine/test-tools/remove/sys/module/mod_simple/refcnt1
-rw-r--r--testsuite/rootfs-pristine/test-util/alias-correct.txt25
-rw-r--r--testsuite/rootfs-pristine/test-util/freadline_wrapped-correct.txt10
-rw-r--r--testsuite/rootfs-pristine/test-util/freadline_wrapped-input.txt8
-rw-r--r--testsuite/rootfs-pristine/test-util2/write-str-safe-correct.txt1
-rwxr-xr-xtestsuite/setup-rootfs.sh181
-rw-r--r--testsuite/stripped-module.h29
-rw-r--r--testsuite/test-array.c201
-rw-r--r--testsuite/test-blacklist.c105
-rw-r--r--testsuite/test-dependencies.c89
-rw-r--r--testsuite/test-depmod.c247
-rw-r--r--testsuite/test-hash.c282
-rw-r--r--testsuite/test-init.c169
-rw-r--r--testsuite/test-initstate.c126
-rw-r--r--testsuite/test-list.c238
-rw-r--r--testsuite/test-loaded.c91
-rw-r--r--testsuite/test-modinfo.c122
-rw-r--r--testsuite/test-modprobe.c469
-rw-r--r--testsuite/test-new-module.c118
-rw-r--r--testsuite/test-scratchbuf.c89
-rw-r--r--testsuite/test-strbuf.c98
-rw-r--r--testsuite/test-testsuite.c163
-rw-r--r--testsuite/test-tools.c71
-rw-r--r--testsuite/test-util.c273
-rw-r--r--testsuite/testsuite.c1119
-rw-r--r--testsuite/testsuite.h191
-rw-r--r--testsuite/uname.c74
377 files changed, 7042 insertions, 0 deletions
diff --git a/testsuite/.gitignore b/testsuite/.gitignore
new file mode 100644
index 0000000..9d26b88
--- /dev/null
+++ b/testsuite/.gitignore
@@ -0,0 +1,57 @@
+*.lo
+*.la
+*.so
+/.dirstamp
+/test-scratchbuf
+/test-strbuf
+/test-array
+/test-util
+/test-blacklist
+/test-dependencies
+/test-depmod
+/test-init
+/test-initstate
+/test-loaded
+/test-modinfo
+/test-new-module
+/test-testsuite
+/test-modprobe
+/test-hash
+/test-list
+/test-tools
+/rootfs
+/stamp-rootfs
+/test-scratchbuf.log
+/test-scratchbuf.trs
+/test-strbuf.log
+/test-strbuf.trs
+/test-array.log
+/test-array.trs
+/test-util.log
+/test-util.trs
+/test-blacklist.log
+/test-blacklist.trs
+/test-dependencies.log
+/test-dependencies.trs
+/test-depmod.log
+/test-depmod.trs
+/test-init.log
+/test-init.trs
+/test-initstate.log
+/test-initstate.trs
+/test-loaded.log
+/test-loaded.trs
+/test-modinfo.log
+/test-modinfo.trs
+/test-modprobe.log
+/test-modprobe.trs
+/test-hash.log
+/test-hash.trs
+/test-new-module.log
+/test-new-module.trs
+/test-testsuite.log
+/test-testsuite.trs
+/test-list.log
+/test-list.trs
+/test-tools.log
+/test-tools.trs
diff --git a/testsuite/COPYING b/testsuite/COPYING
new file mode 100644
index 0000000..8add30a
--- /dev/null
+++ b/testsuite/COPYING
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/testsuite/Makefile b/testsuite/Makefile
new file mode 100644
index 0000000..38ba552
--- /dev/null
+++ b/testsuite/Makefile
@@ -0,0 +1,15 @@
+# Copyright 2010 Lennart Poettering
+#
+# This file has been copied from systemd. It is a dirty trick to simplify
+# compilation when CWD is not the root of the source tree. This file is not
+# intended to be distributed. So, don't touch it, even better ignore it!
+
+all:
+ $(MAKE) -C .. check
+check:
+ $(MAKE) -C .. check
+
+clean:
+ $(MAKE) -C .. clean
+
+.PHONY: all clean check
diff --git a/testsuite/README b/testsuite/README
new file mode 100644
index 0000000..052569f
--- /dev/null
+++ b/testsuite/README
@@ -0,0 +1,61 @@
+testsuite
+
+OVERVIEW
+========
+
+Kmod's testsuite was designed to automate the process of running tests with
+different scenarios, configurations and architectures. The idea is that once we
+received a bug report, we reproduce it using the testsuite so we avoid
+recurring on the same bug in future.
+
+
+FEATURES
+========
+
+- Isolate each test by running them in separate processes;
+- Exec a binary, so we can test the tools and not only the lib API
+- Fake accesses to filesystem so we can provide a test rootfs with all the
+ configuration, indexes, etc that test needs to be executed.
+- Fake calls to init_module(), delete_module() and uname(), so we don't have to
+ run tests as root and figure out how to deal with different architectures.
+
+HOW TO ADD A TEST
+=================
+
+The simplest way to add a test is to copy and paste one already there. Most of
+the options you can have are covered by another tests. This is what you need to
+pay attention when writing a test:
+
+1 - Look at testsuite.h, struct test, to see all the options available.
+
+2 - Use TESTSUITE_MAIN and DEFINE_TEST to add new tests. Don't forget to fill
+ its description.
+
+3 - If you want testsuite to compare the stdout/stderr of your tests in order
+ to check if it worked or not, fill in output.{stderr,stdout} the file with
+ the expected output. Bear in mind the same file is used for all
+ architectures, so don't print arch-dependent content if you are comparing
+ the output.
+
+4 - Fill in the config vector. Setting any of these configuration will make
+ testsuite to export LD_PRELOAD with the necessary override libs before
+ executing the test. If you are not exec'ing an external binary, you need to
+ pass "need_spawn = true" below, otherwise it will not work (LD_PRELOAD is
+ only applied when exec'ing a binary). See each config description in
+ testsuite.h
+
+5 - need_spawn: if testsuite will exec itself before running a test
+
+6 - expected_fail: if that test is expected to fail, i.e. the return code is
+ expected not to be 0.
+
+7 - The rootfs is populated by copying the entire contents of rootfs-pristine
+ then running populate-modules.sh to copy generated modules from
+ module-playground. Update the latter script to include any modules your
+ test need.
+
+8 - Tests can be run individually, outside of 'make check'. strace and gdb work
+ too, as long as you tell them to operate on child process.
+
+9 - Make sure test passes when using "default" build flags, i.e. by running
+ 'autogen.sh c'
diff --git a/testsuite/delete_module.c b/testsuite/delete_module.c
new file mode 100644
index 0000000..f3ae20b
--- /dev/null
+++ b/testsuite/delete_module.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2012-2013 ProFUSION embedded systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <shared/util.h>
+
+#include "testsuite.h"
+
+struct mod {
+ struct mod *next;
+ int ret;
+ int errcode;
+ char name[];
+};
+
+static struct mod *modules;
+static bool need_init = true;
+
+static void parse_retcodes(struct mod **_modules, const char *s)
+{
+ const char *p;
+
+ if (s == NULL)
+ return;
+
+ for (p = s;;) {
+ struct mod *mod;
+ const char *modname;
+ char *end;
+ size_t modnamelen;
+ int ret, errcode;
+ long l;
+
+ modname = p;
+ if (modname == NULL || modname[0] == '\0')
+ break;
+
+ modnamelen = strcspn(p, ":");
+ if (modname[modnamelen] != ':')
+ break;
+
+ p = modname + modnamelen + 1;
+ if (p == NULL)
+ break;
+
+ l = strtol(p, &end, 0);
+ if (end == p || *end != ':')
+ break;
+
+ ret = (int) l;
+ p = end + 1;
+
+ l = strtol(p, &end, 0);
+ if (*end == ':')
+ p = end + 1;
+ else if (*end != '\0')
+ break;
+
+ errcode = (int) l;
+
+ mod = malloc(sizeof(*mod) + modnamelen + 1);
+ if (mod == NULL)
+ break;
+
+ memcpy(mod->name, modname, modnamelen);
+ mod->name[modnamelen] = '\0';
+ mod->ret = ret;
+ mod->errcode = errcode;
+ mod->next = *_modules;
+ *_modules = mod;
+ }
+}
+
+static struct mod *find_module(struct mod *_modules, const char *modname)
+{
+ struct mod *mod;
+
+ for (mod = _modules; mod != NULL; mod = mod->next) {
+ if (streq(mod->name, modname))
+ return mod;
+ }
+
+ return NULL;
+}
+
+static void init_retcodes(void)
+{
+ const char *s;
+ struct mod *mod;
+
+ if (!need_init)
+ return;
+
+ need_init = false;
+ s = getenv(S_TC_DELETE_MODULE_RETCODES);
+ if (s == NULL) {
+ ERR("TRAP delete_module(): missing export %s?\n",
+ S_TC_DELETE_MODULE_RETCODES);
+ }
+
+ parse_retcodes(&modules, s);
+
+ for (mod = modules; mod != NULL; mod = mod->next) {
+ LOG("Added module to test delete_module:\n");
+ LOG("\tname=%s ret=%d errcode=%d\n",
+ mod->name, mod->ret, mod->errcode);
+ }
+}
+
+TS_EXPORT long delete_module(const char *name, unsigned int flags);
+
+/*
+ * FIXME: change /sys/module/<modname> to fake-remove a module
+ *
+ * Default behavior is to exit successfully. If this is not the intended
+ * behavior, set TESTSUITE_DELETE_MODULE_RETCODES env var.
+ */
+long delete_module(const char *modname, unsigned int flags)
+{
+ struct mod *mod;
+
+ init_retcodes();
+ mod = find_module(modules, modname);
+ if (mod == NULL)
+ return 0;
+
+ errno = mod->errcode;
+ return mod->ret;
+}
+
+/* the test is going away anyway, but lets keep valgrind happy */
+void free_resources(void) __attribute__((destructor));
+void free_resources(void)
+{
+ while (modules) {
+ struct mod *mod = modules->next;
+ free(modules);
+ modules = mod;
+ }
+}
diff --git a/testsuite/init_module.c b/testsuite/init_module.c
new file mode 100644
index 0000000..503e703
--- /dev/null
+++ b/testsuite/init_module.c
@@ -0,0 +1,403 @@
+/*
+ * Copyright (C) 2012-2013 ProFUSION embedded systems
+ * Copyright (C) 2012-2013 Lucas De Marchi <lucas.de.marchi@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HAVE_FINIT_MODULE
+#define HAVE_FINIT_MODULE 1
+#endif
+
+#include <assert.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <elf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+
+#include <shared/util.h>
+
+/* kmod_elf_get_section() is not exported, we need the private header */
+#include <libkmod/libkmod-internal.h>
+
+/* FIXME: hack, change name so we don't clash */
+#undef ERR
+#include "testsuite.h"
+#include "stripped-module.h"
+
+struct mod {
+ struct mod *next;
+ int ret;
+ int errcode;
+ char name[];
+};
+
+static struct mod *modules;
+static bool need_init = true;
+static struct kmod_ctx *ctx;
+
+static void parse_retcodes(struct mod *_modules, const char *s)
+{
+ const char *p;
+
+ if (s == NULL)
+ return;
+
+ for (p = s;;) {
+ struct mod *mod;
+ const char *modname;
+ char *end;
+ size_t modnamelen;
+ int ret, errcode;
+ long l;
+
+ modname = p;
+ if (modname == NULL || modname[0] == '\0')
+ break;
+
+ modnamelen = strcspn(s, ":");
+ if (modname[modnamelen] != ':')
+ break;
+
+ p = modname + modnamelen + 1;
+ if (p == NULL)
+ break;
+
+ l = strtol(p, &end, 0);
+ if (end == p || *end != ':')
+ break;
+ ret = (int) l;
+ p = end + 1;
+
+ l = strtol(p, &end, 0);
+ if (*end == ':')
+ p = end + 1;
+ else if (*end != '\0')
+ break;
+
+ errcode = (int) l;
+
+ mod = malloc(sizeof(*mod) + modnamelen + 1);
+ if (mod == NULL)
+ break;
+
+ memcpy(mod->name, modname, modnamelen);
+ mod->name[modnamelen] = '\0';
+ mod->ret = ret;
+ mod->errcode = errcode;
+ mod->next = _modules;
+ _modules = mod;
+ }
+}
+
+static int write_one_line_file(const char *fn, const char *line, int len)
+{
+ FILE *f;
+ int r;
+
+ assert(fn);
+ assert(line);
+
+ f = fopen(fn, "we");
+ if (!f)
+ return -errno;
+
+ errno = 0;
+ if (fputs(line, f) < 0) {
+ r = -errno;
+ goto finish;
+ }
+
+ fflush(f);
+
+ if (ferror(f)) {
+ if (errno != 0)
+ r = -errno;
+ else
+ r = -EIO;
+ } else
+ r = 0;
+
+finish:
+ fclose(f);
+ return r;
+}
+
+static int create_sysfs_files(const char *modname)
+{
+ char buf[PATH_MAX];
+ const char *sysfsmod = "/sys/module/";
+ int len = strlen(sysfsmod);
+
+ memcpy(buf, sysfsmod, len);
+ strcpy(buf + len, modname);
+ len += strlen(modname);
+
+ assert(mkdir_p(buf, len, 0755) >= 0);
+
+ strcpy(buf + len, "/initstate");
+ return write_one_line_file(buf, "live\n", strlen("live\n"));
+}
+
+static struct mod *find_module(struct mod *_modules, const char *modname)
+{
+ struct mod *mod;
+
+ for (mod = _modules; mod != NULL; mod = mod->next) {
+ if (streq(mod->name, modname))
+ return mod;
+ }
+
+ return NULL;
+}
+
+static void init_retcodes(void)
+{
+ const char *s;
+
+ if (!need_init)
+ return;
+
+ need_init = false;
+ s = getenv(S_TC_INIT_MODULE_RETCODES);
+ if (s == NULL) {
+ fprintf(stderr, "TRAP init_module(): missing export %s?\n",
+ S_TC_INIT_MODULE_RETCODES);
+ }
+
+ ctx = kmod_new(NULL, NULL);
+
+ parse_retcodes(modules, s);
+}
+
+static inline bool module_is_inkernel(const char *modname)
+{
+ struct kmod_module *mod;
+ int state;
+ bool ret;
+
+ if (kmod_module_new_from_name(ctx, modname, &mod) < 0)
+ return false;
+
+ state = kmod_module_get_initstate(mod);
+
+ if (state == KMOD_MODULE_LIVE ||
+ state == KMOD_MODULE_BUILTIN)
+ ret = true;
+ else
+ ret = false;
+
+ kmod_module_unref(mod);
+
+ return ret;
+}
+
+static uint8_t elf_identify(void *mem)
+{
+ uint8_t *p = mem;
+ return p[EI_CLASS];
+}
+
+TS_EXPORT long init_module(void *mem, unsigned long len, const char *args);
+
+/*
+ * Default behavior is to try to mimic init_module behavior inside the kernel.
+ * If it is a simple test that you know the error code, set the return code
+ * in TESTSUITE_INIT_MODULE_RETCODES env var instead.
+ *
+ * The exception is when the module name is not find in the memory passed.
+ * This is because we want to be able to pass dummy modules (and not real
+ * ones) and it still work.
+ */
+long init_module(void *mem, unsigned long len, const char *args)
+{
+ const char *modname;
+ struct kmod_elf *elf;
+ struct mod *mod;
+ const void *buf;
+ uint64_t bufsize;
+ int err;
+ uint8_t class;
+ off_t offset;
+
+ init_retcodes();
+
+ elf = kmod_elf_new(mem, len);
+ if (elf == NULL)
+ return 0;
+
+ err = kmod_elf_get_section(elf, ".gnu.linkonce.this_module", &buf,
+ &bufsize);
+ kmod_elf_unref(elf);
+
+ /* We couldn't parse the ELF file. Just exit as if it was successful */
+ if (err < 0)
+ return 0;
+
+ /* We need to open both 32 and 64 bits module - hack! */
+ class = elf_identify(mem);
+ if (class == ELFCLASS64)
+ offset = MODULE_NAME_OFFSET_64;
+ else
+ offset = MODULE_NAME_OFFSET_32;
+
+ modname = (char *)buf + offset;
+ mod = find_module(modules, modname);
+ if (mod != NULL) {
+ errno = mod->errcode;
+ err = mod->ret;
+ } else if (module_is_inkernel(modname)) {
+ err = -1;
+ errno = EEXIST;
+ } else
+ err = 0;
+
+ if (err == 0)
+ create_sysfs_files(modname);
+
+ return err;
+}
+
+static int check_kernel_version(int major, int minor)
+{
+ struct utsname u;
+ const char *p;
+ int maj = 0, min = 0;
+
+ if (uname(&u) < 0)
+ return false;
+ for (p = u.release; *p >= '0' && *p <= '9'; p++)
+ maj = maj * 10 + *p - '0';
+ if (*p == '.')
+ for (p++; *p >= '0' && *p <= '9'; p++)
+ min = min * 10 + *p - '0';
+ if (maj > major || (maj == major && min >= minor))
+ return true;
+ return false;
+}
+
+
+TS_EXPORT int finit_module(const int fd, const char *args, const int flags);
+
+int finit_module(const int fd, const char *args, const int flags)
+{
+ int err;
+ void *mem;
+ unsigned long len;
+ struct stat st;
+
+ if (!check_kernel_version(3, 8)) {
+ errno = ENOSYS;
+ return -1;
+ }
+ if (fstat(fd, &st) < 0)
+ return -1;
+
+ len = st.st_size;
+ mem = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (mem == MAP_FAILED)
+ return -1;
+
+ err = init_module(mem, len, args);
+ munmap(mem, len);
+
+ return err;
+}
+
+TS_EXPORT long int syscall(long int __sysno, ...)
+{
+ va_list ap;
+ long ret;
+
+ if (__sysno == -1) {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ if (__sysno == __NR_finit_module) {
+ const char *args;
+ int flags;
+ int fd;
+
+ va_start(ap, __sysno);
+
+ fd = va_arg(ap, int);
+ args = va_arg(ap, const char *);
+ flags = va_arg(ap, int);
+
+ ret = finit_module(fd, args, flags);
+
+ va_end(ap);
+ return ret;
+ }
+
+ if (__sysno == __NR_gettid) {
+ static void *nextlib = NULL;
+ static long (*nextlib_syscall)(long number, ...);
+
+ if (nextlib_syscall == NULL) {
+#ifdef RTLD_NEXT
+ nextlib = RTLD_NEXT;
+#else
+ nextlib = dlopen("libc.so.6", RTLD_LAZY);
+#endif
+ nextlib_syscall = dlsym(nextlib, "syscall");
+ if (nextlib_syscall == NULL) {
+ fprintf(stderr, "FIXME FIXME FIXME: could not load syscall symbol: %s\n",
+ dlerror());
+ abort();
+ }
+ }
+
+ return nextlib_syscall(__NR_gettid);
+ }
+
+ /*
+ * FIXME: no way to call the libc function due since this is a
+ * variadic argument function and we don't have a vsyscall() variant
+ * this may fail if a library or process is trying to call syscall()
+ * directly, for example to implement gettid().
+ */
+ fprintf(stderr, "FIXME FIXME FIXME: could not wrap call to syscall(%ld), this should not happen\n",
+ __sysno);
+
+ abort();
+}
+
+/* the test is going away anyway, but lets keep valgrind happy */
+void free_resources(void) __attribute__((destructor));
+void free_resources(void)
+{
+ while (modules) {
+ struct mod *mod = modules->next;
+ free(modules);
+ modules = mod;
+ }
+
+ if (ctx)
+ kmod_unref(ctx);
+}
diff --git a/testsuite/module-playground/.gitignore b/testsuite/module-playground/.gitignore
new file mode 100644
index 0000000..6d9c7b1
--- /dev/null
+++ b/testsuite/module-playground/.gitignore
@@ -0,0 +1,16 @@
+*.ko
+!mod-simple-*.ko
+!cache/*.ko
+.cache.mk
+*.mod.c
+.tmp_versions
+*.mod
+*.a
+*.cmd
+*.o.d
+
+modules.order
+Module.symvers
+mod-simple-x86_64.c
+mod-simple-i386.c
+mod-simple-sparc64.c
diff --git a/testsuite/module-playground/Makefile b/testsuite/module-playground/Makefile
new file mode 100644
index 0000000..a7ab09b
--- /dev/null
+++ b/testsuite/module-playground/Makefile
@@ -0,0 +1,83 @@
+ifneq ($(KERNELRELEASE),)
+# kbuild part of makefile
+
+ifneq ($(KMOD_TESTSUITE_ARCH_BUILD),1)
+obj-m := mod-simple.o
+
+# mod-foo depends on foo-x, and foo-x modules don't depend
+# on anyone
+obj-m += mod-foo-a.o
+obj-m += mod-foo-b.o
+obj-m += mod-foo-c.o
+obj-m += mod-foo.o
+
+# mod-loop: create loops in dependencies:
+# 1) mod-loop-a -> mod-loop-b -> mod-loop-c -> mod-loop-a
+# |-> mod-loop-f |-> mod-loop-f
+# \-> mod-loop-g \-> mod-loop-g
+# 2) mod-loop-d -> mod-loop-e -> mod-loop-d
+# 3.1) mod-loop-h -> mod-loop-i -> mod-loop-j -> mod-loop-h
+# 3.2) mod-loop-h -> mod-loop-i -> mod-loop-j -> mod-loop-k -> mod-loop-h
+
+obj-m += mod-loop-a.o
+obj-m += mod-loop-b.o
+obj-m += mod-loop-c.o
+obj-m += mod-loop-d.o
+obj-m += mod-loop-e.o
+obj-m += mod-loop-f.o
+obj-m += mod-loop-g.o
+obj-m += mod-loop-h.o
+obj-m += mod-loop-i.o
+obj-m += mod-loop-j.o
+obj-m += mod-loop-k.o
+
+# mod-fake-*: fake the respective modules in kernel with these aliases. Aliases
+# list was taken from 3.5.4
+obj-m += mod-fake-hpsa.o
+obj-m += mod-fake-scsi-mod.o
+obj-m += mod-fake-cciss.o
+
+else
+# only build ARCH-specific module
+ifeq ($(ARCH),)
+ $(error ARCH must be set to a valid architecture)
+endif
+obj-m := mod-simple-$(ARCH).o
+endif
+
+else
+# normal makefile
+KDIR ?= $(module_prefix)/lib/modules/`uname -r`/build
+KVER ?= `uname -r`
+ifeq ($(FAKE_BUILD),)
+ FAKE_BUILD=0
+endif
+
+ARCH_SPECIFIC_MODULES := mod-simple-x86_64.ko mod-simple-i386.ko mod-simple-sparc64.ko
+MY_MODULES := $(filter-out $(ARCH_SPECIFIC_MODULES),$(wildcard *.ko))
+
+default: modules arch-modules
+
+mod-simple-%.ko: mod-simple-%.c Makefile.arch
+ $(eval arch=$(patsubst mod-simple-%.ko,%,$@))
+ $(MAKE) KDIR=$(KDIR_$(arch)) ARCH=$(arch) CROSS_COMPILE=$(CROSS_COMPILE_$(arch)) -f Makefile.arch
+
+ifeq ($(FAKE_BUILD),0)
+modules:
+ $(MAKE) -C $(KDIR) M=$$PWD
+else
+modules:
+ @echo " CP cache/*.ko"
+ @cp cache/*.ko .
+endif
+
+arch-modules: $(ARCH_SPECIFIC_MODULES)
+
+clean:
+ test -z "$(MY_MODULES)" || rm -rf $(MY_MODULES) || true
+ rm -rf .tmp_versions || true
+ rm -rf .*.cmd *.mod.c || true
+ rm -rf *.o || true
+ rm -rf Module.symvers modules.order
+
+endif
diff --git a/testsuite/module-playground/Makefile.arch b/testsuite/module-playground/Makefile.arch
new file mode 100644
index 0000000..47bd9cb
--- /dev/null
+++ b/testsuite/module-playground/Makefile.arch
@@ -0,0 +1,14 @@
+ifeq ($(ARCH),)
+ $(error ARCH must be set to a valid architecture)
+endif
+
+default:
+ @cmp --quiet mod-simple.c mod-simple-$(ARCH).c || ( \
+ ln -sf mod-simple.c mod-simple-$(ARCH).c; \
+ /bin/false \
+ )
+ $(MAKE) -C $(KDIR_$(ARCH)) CROSS_COMPILE=$(CROSS_COMPILE_$(ARCH)) M=$$PWD KMOD_TESTSUITE_ARCH_BUILD=1
+
+clean:
+ $(MAKE) -C $(KDIR_$(ARCH)) CROSS_COMPILE=$(CROSS_COMPILE_$(ARCH)) M=$$PWD KMOD_TESTSUITE_ARCH_BUILD=1 clean
+ rm -f mod-simple-$(ARCH).c
diff --git a/testsuite/module-playground/README b/testsuite/module-playground/README
new file mode 100644
index 0000000..76c6e8d
--- /dev/null
+++ b/testsuite/module-playground/README
@@ -0,0 +1,26 @@
+Pre-compiled modules
+====================
+
+Some modules are pre-compiled due to needing cross-compilers present on the
+build/dev machine which is inconvenient. Makefile is ready to compile them again
+in case they are missing:
+
+1) Prepare the linux kernel trees to build external modules, i.e.:
+
+ kernel $ make ARCH=<arch> CROSS_COMPILER=<cross-compiler-prefix> defconfig
+ kernel $ make ARCH=<arch> CROSS_COMPILER=<cross-compiler-prefix> modules_prepare
+
+ For each architecture. See the Makefile to check which are the supported architectures.
+
+2) Export the variables below to point to the right place:
+
+ KDIR_<arch>: for each architecture it needs to point to a
+ kernel tree configured as in (1)
+
+ CROSS_COMPILER_<arch: for each architecture it needs to point to the
+ correct toolchain prefix. Leave it blank if a
+ cross-compiler is not needed (example: you are
+ building a 32b module with a multilib compiler).
+
+
+3) Remove every %-<arch>.ko. After this the build system will recreate them.
diff --git a/testsuite/module-playground/cache/mod-fake-cciss.ko b/testsuite/module-playground/cache/mod-fake-cciss.ko
new file mode 100644
index 0000000..f61409a
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-fake-cciss.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-fake-hpsa.ko b/testsuite/module-playground/cache/mod-fake-hpsa.ko
new file mode 100644
index 0000000..3d33ba7
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-fake-hpsa.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-fake-scsi-mod.ko b/testsuite/module-playground/cache/mod-fake-scsi-mod.ko
new file mode 100644
index 0000000..c0eb974
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-fake-scsi-mod.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-foo-a.ko b/testsuite/module-playground/cache/mod-foo-a.ko
new file mode 100644
index 0000000..f2d406e
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-foo-a.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-foo-b.ko b/testsuite/module-playground/cache/mod-foo-b.ko
new file mode 100644
index 0000000..53bf3a9
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-foo-b.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-foo-c.ko b/testsuite/module-playground/cache/mod-foo-c.ko
new file mode 100644
index 0000000..083e801
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-foo-c.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-foo.ko b/testsuite/module-playground/cache/mod-foo.ko
new file mode 100644
index 0000000..0961478
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-foo.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-loop-a.ko b/testsuite/module-playground/cache/mod-loop-a.ko
new file mode 100644
index 0000000..51533d8
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-loop-a.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-loop-b.ko b/testsuite/module-playground/cache/mod-loop-b.ko
new file mode 100644
index 0000000..5e20348
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-loop-b.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-loop-c.ko b/testsuite/module-playground/cache/mod-loop-c.ko
new file mode 100644
index 0000000..6a02b04
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-loop-c.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-loop-d.ko b/testsuite/module-playground/cache/mod-loop-d.ko
new file mode 100644
index 0000000..3ab3348
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-loop-d.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-loop-e.ko b/testsuite/module-playground/cache/mod-loop-e.ko
new file mode 100644
index 0000000..efe93ff
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-loop-e.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-loop-f.ko b/testsuite/module-playground/cache/mod-loop-f.ko
new file mode 100644
index 0000000..c0e15cb
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-loop-f.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-loop-g.ko b/testsuite/module-playground/cache/mod-loop-g.ko
new file mode 100644
index 0000000..46f3c43
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-loop-g.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-loop-h.ko b/testsuite/module-playground/cache/mod-loop-h.ko
new file mode 100644
index 0000000..cbd81e5
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-loop-h.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-loop-i.ko b/testsuite/module-playground/cache/mod-loop-i.ko
new file mode 100644
index 0000000..045bc4f
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-loop-i.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-loop-j.ko b/testsuite/module-playground/cache/mod-loop-j.ko
new file mode 100644
index 0000000..067aa4b
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-loop-j.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-loop-k.ko b/testsuite/module-playground/cache/mod-loop-k.ko
new file mode 100644
index 0000000..2cc16d1
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-loop-k.ko
Binary files differ
diff --git a/testsuite/module-playground/cache/mod-simple.ko b/testsuite/module-playground/cache/mod-simple.ko
new file mode 100644
index 0000000..2c5ffcf
--- /dev/null
+++ b/testsuite/module-playground/cache/mod-simple.ko
Binary files differ
diff --git a/testsuite/module-playground/dummy.pkcs7 b/testsuite/module-playground/dummy.pkcs7
new file mode 100644
index 0000000..bcdb902
--- /dev/null
+++ b/testsuite/module-playground/dummy.pkcs7
Binary files differ
diff --git a/testsuite/module-playground/dummy.sha1 b/testsuite/module-playground/dummy.sha1
new file mode 100644
index 0000000..bab65d3
--- /dev/null
+++ b/testsuite/module-playground/dummy.sha1
Binary files differ
diff --git a/testsuite/module-playground/dummy.sha256 b/testsuite/module-playground/dummy.sha256
new file mode 100644
index 0000000..fe16b01
--- /dev/null
+++ b/testsuite/module-playground/dummy.sha256
Binary files differ
diff --git a/testsuite/module-playground/mod-fake-cciss.c b/testsuite/module-playground/mod-fake-cciss.c
new file mode 100644
index 0000000..9c46801
--- /dev/null
+++ b/testsuite/module-playground/mod-fake-cciss.c
@@ -0,0 +1,37 @@
+#include <linux/init.h>
+#include <linux/module.h>
+
+static int __init test_module_init(void)
+{
+ return 0;
+}
+
+static void test_module_exit(void)
+{
+}
+module_init(test_module_init);
+module_exit(test_module_exit);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
+
+MODULE_ALIAS("pci:v00000E11d0000B060sv00000E11sd00004070bc*sc*i*");
+MODULE_ALIAS("pci:v00000E11d0000B178sv00000E11sd00004080bc*sc*i*");
+MODULE_ALIAS("pci:v00000E11d0000B178sv00000E11sd00004082bc*sc*i*");
+MODULE_ALIAS("pci:v00000E11d0000B178sv00000E11sd00004083bc*sc*i*");
+MODULE_ALIAS("pci:v00000E11d00000046sv00000E11sd00004091bc*sc*i*");
+MODULE_ALIAS("pci:v00000E11d00000046sv00000E11sd0000409Abc*sc*i*");
+MODULE_ALIAS("pci:v00000E11d00000046sv00000E11sd0000409Bbc*sc*i*");
+MODULE_ALIAS("pci:v00000E11d00000046sv00000E11sd0000409Cbc*sc*i*");
+MODULE_ALIAS("pci:v00000E11d00000046sv00000E11sd0000409Dbc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd00003220sv0000103Csd00003225bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd00003230sv0000103Csd00003223bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd00003230sv0000103Csd00003234bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd00003230sv0000103Csd00003235bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd00003238sv0000103Csd00003211bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd00003238sv0000103Csd00003212bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd00003238sv0000103Csd00003213bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd00003238sv0000103Csd00003214bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd00003238sv0000103Csd00003215bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd00003230sv0000103Csd00003237bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd00003230sv0000103Csd0000323Dbc*sc*i*");
diff --git a/testsuite/module-playground/mod-fake-hpsa.c b/testsuite/module-playground/mod-fake-hpsa.c
new file mode 100644
index 0000000..99dc729
--- /dev/null
+++ b/testsuite/module-playground/mod-fake-hpsa.c
@@ -0,0 +1,36 @@
+#include <linux/init.h>
+#include <linux/module.h>
+
+extern void dummy_export(void);
+
+static int __init test_module_init(void)
+{
+ dummy_export();
+ return 0;
+}
+
+static void test_module_exit(void)
+{
+}
+module_init(test_module_init);
+module_exit(test_module_exit);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
+
+MODULE_ALIAS("pci:v0000103Cd0000323Asv0000103Csd00003241bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd0000323Asv0000103Csd00003243bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd0000323Asv0000103Csd00003245bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd0000323Asv0000103Csd00003247bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd0000323Asv0000103Csd00003249bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd0000323Asv0000103Csd0000324Abc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd0000323Asv0000103Csd0000324Bbc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd0000323Asv0000103Csd00003233bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd0000323Bsv0000103Csd00003350bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd0000323Bsv0000103Csd00003351bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd0000323Bsv0000103Csd00003352bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd0000323Bsv0000103Csd00003353bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd0000323Bsv0000103Csd00003354bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd0000323Bsv0000103Csd00003355bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd0000323Bsv0000103Csd00003356bc*sc*i*");
+MODULE_ALIAS("pci:v0000103Cd*sv*sd*bc01sc04i*");
diff --git a/testsuite/module-playground/mod-fake-scsi-mod.c b/testsuite/module-playground/mod-fake-scsi-mod.c
new file mode 100644
index 0000000..916a04d
--- /dev/null
+++ b/testsuite/module-playground/mod-fake-scsi-mod.c
@@ -0,0 +1,21 @@
+#include <linux/init.h>
+#include <linux/module.h>
+
+static int __init test_module_init(void)
+{
+ return 0;
+}
+
+static void test_module_exit(void)
+{
+}
+module_init(test_module_init);
+module_exit(test_module_exit);
+
+void dummy_export(void)
+{
+}
+EXPORT_SYMBOL(dummy_export);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
diff --git a/testsuite/module-playground/mod-foo-a.c b/testsuite/module-playground/mod-foo-a.c
new file mode 100644
index 0000000..bc65f66
--- /dev/null
+++ b/testsuite/module-playground/mod-foo-a.c
@@ -0,0 +1,20 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+static int __init foo_init(void)
+{
+ return 0;
+}
+module_init(foo_init);
+
+void print_fooA(void)
+{
+ pr_warn("fooA\n");
+}
+EXPORT_SYMBOL(print_fooA);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
diff --git a/testsuite/module-playground/mod-foo-b.c b/testsuite/module-playground/mod-foo-b.c
new file mode 100644
index 0000000..09079f6
--- /dev/null
+++ b/testsuite/module-playground/mod-foo-b.c
@@ -0,0 +1,20 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+static int __init foo_init(void)
+{
+ return 0;
+}
+module_init(foo_init);
+
+void print_fooB(void)
+{
+ pr_warn("fooB\n");
+}
+EXPORT_SYMBOL(print_fooB);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
diff --git a/testsuite/module-playground/mod-foo-c.c b/testsuite/module-playground/mod-foo-c.c
new file mode 100644
index 0000000..3afd35d
--- /dev/null
+++ b/testsuite/module-playground/mod-foo-c.c
@@ -0,0 +1,20 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+static int __init foo_init(void)
+{
+ return 0;
+}
+module_init(foo_init);
+
+void print_fooC(void)
+{
+ pr_warn("fooC\n");
+}
+EXPORT_SYMBOL(print_fooC);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
diff --git a/testsuite/module-playground/mod-foo.c b/testsuite/module-playground/mod-foo.c
new file mode 100644
index 0000000..8105608
--- /dev/null
+++ b/testsuite/module-playground/mod-foo.c
@@ -0,0 +1,23 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+void print_fooA(void);
+void print_fooB(void);
+void print_fooC(void);
+
+static int __init foo_init(void)
+{
+ print_fooA();
+ print_fooB();
+ print_fooC();
+
+ return 0;
+}
+
+module_init(foo_init);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
diff --git a/testsuite/module-playground/mod-loop-a.c b/testsuite/module-playground/mod-loop-a.c
new file mode 100644
index 0000000..e5adb49
--- /dev/null
+++ b/testsuite/module-playground/mod-loop-a.c
@@ -0,0 +1,27 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+#include "mod-loop.h"
+
+static int __init test_module_init(void)
+{
+ printA();
+ printB();
+ printF();
+ printG();
+
+ return 0;
+}
+module_init(test_module_init);
+
+void printA(void)
+{
+ pr_warn("Hello, world A\n");
+}
+EXPORT_SYMBOL(printA);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
diff --git a/testsuite/module-playground/mod-loop-b.c b/testsuite/module-playground/mod-loop-b.c
new file mode 100644
index 0000000..26232ea
--- /dev/null
+++ b/testsuite/module-playground/mod-loop-b.c
@@ -0,0 +1,27 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+#include "mod-loop.h"
+
+static int __init test_module_init(void)
+{
+ printB();
+ printC();
+ printF();
+ printG();
+
+ return 0;
+}
+module_init(test_module_init);
+
+void printB(void)
+{
+ pr_warn("Hello, world B\n");
+}
+EXPORT_SYMBOL(printB);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
diff --git a/testsuite/module-playground/mod-loop-c.c b/testsuite/module-playground/mod-loop-c.c
new file mode 100644
index 0000000..0b90f7f
--- /dev/null
+++ b/testsuite/module-playground/mod-loop-c.c
@@ -0,0 +1,25 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+#include "mod-loop.h"
+
+static int __init test_module_init(void)
+{
+ printC();
+ printA();
+
+ return 0;
+}
+module_init(test_module_init);
+
+void printC(void)
+{
+ pr_warn("Hello, world C\n");
+}
+EXPORT_SYMBOL(printC);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
diff --git a/testsuite/module-playground/mod-loop-d.c b/testsuite/module-playground/mod-loop-d.c
new file mode 100644
index 0000000..9b52305
--- /dev/null
+++ b/testsuite/module-playground/mod-loop-d.c
@@ -0,0 +1,25 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+#include "mod-loop.h"
+
+static int __init test_module_init(void)
+{
+ printD();
+ printE();
+
+ return 0;
+}
+module_init(test_module_init);
+
+void printD(void)
+{
+ pr_warn("Hello, world D\n");
+}
+EXPORT_SYMBOL(printD);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
diff --git a/testsuite/module-playground/mod-loop-e.c b/testsuite/module-playground/mod-loop-e.c
new file mode 100644
index 0000000..a65acb2
--- /dev/null
+++ b/testsuite/module-playground/mod-loop-e.c
@@ -0,0 +1,25 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+#include "mod-loop.h"
+
+static int __init test_module_init(void)
+{
+ printE();
+ printD();
+
+ return 0;
+}
+module_init(test_module_init);
+
+void printE(void)
+{
+ pr_warn("Hello, world E\n");
+}
+EXPORT_SYMBOL(printE);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
diff --git a/testsuite/module-playground/mod-loop-f.c b/testsuite/module-playground/mod-loop-f.c
new file mode 100644
index 0000000..0abb161
--- /dev/null
+++ b/testsuite/module-playground/mod-loop-f.c
@@ -0,0 +1,24 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+#include "mod-loop.h"
+
+static int __init test_module_init(void)
+{
+ printF();
+
+ return 0;
+}
+module_init(test_module_init);
+
+void printF(void)
+{
+ pr_warn("Hello, world F\n");
+}
+EXPORT_SYMBOL(printF);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
diff --git a/testsuite/module-playground/mod-loop-g.c b/testsuite/module-playground/mod-loop-g.c
new file mode 100644
index 0000000..0965d76
--- /dev/null
+++ b/testsuite/module-playground/mod-loop-g.c
@@ -0,0 +1,24 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+#include "mod-loop.h"
+
+static int __init test_module_init(void)
+{
+ printG();
+
+ return 0;
+}
+module_init(test_module_init);
+
+void printG(void)
+{
+ pr_warn("Hello, world G\n");
+}
+EXPORT_SYMBOL(printG);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
diff --git a/testsuite/module-playground/mod-loop-h.c b/testsuite/module-playground/mod-loop-h.c
new file mode 100644
index 0000000..6f457e2
--- /dev/null
+++ b/testsuite/module-playground/mod-loop-h.c
@@ -0,0 +1,25 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+#include "mod-loop.h"
+
+static int __init test_module_init(void)
+{
+ printH();
+ printI();
+
+ return 0;
+}
+module_init(test_module_init);
+
+void printH(void)
+{
+ pr_warn("Hello, world H\n");
+}
+EXPORT_SYMBOL(printH);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
diff --git a/testsuite/module-playground/mod-loop-i.c b/testsuite/module-playground/mod-loop-i.c
new file mode 100644
index 0000000..6456217
--- /dev/null
+++ b/testsuite/module-playground/mod-loop-i.c
@@ -0,0 +1,25 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+#include "mod-loop.h"
+
+static int __init test_module_init(void)
+{
+ printI();
+ printJ();
+
+ return 0;
+}
+module_init(test_module_init);
+
+void printI(void)
+{
+ pr_warn("Hello, world I\n");
+}
+EXPORT_SYMBOL(printI);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
diff --git a/testsuite/module-playground/mod-loop-j.c b/testsuite/module-playground/mod-loop-j.c
new file mode 100644
index 0000000..facc81f
--- /dev/null
+++ b/testsuite/module-playground/mod-loop-j.c
@@ -0,0 +1,26 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+#include "mod-loop.h"
+
+static int __init test_module_init(void)
+{
+ printJ();
+ printH();
+ printK();
+
+ return 0;
+}
+module_init(test_module_init);
+
+void printJ(void)
+{
+ pr_warn("Hello, world J\n");
+}
+EXPORT_SYMBOL(printJ);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
diff --git a/testsuite/module-playground/mod-loop-k.c b/testsuite/module-playground/mod-loop-k.c
new file mode 100644
index 0000000..49386cc
--- /dev/null
+++ b/testsuite/module-playground/mod-loop-k.c
@@ -0,0 +1,25 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+
+#include "mod-loop.h"
+
+static int __init test_module_init(void)
+{
+ printK();
+ printH();
+
+ return 0;
+}
+module_init(test_module_init);
+
+void printK(void)
+{
+ pr_warn("Hello, world K\n");
+}
+EXPORT_SYMBOL(printK);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("LGPL");
diff --git a/testsuite/module-playground/mod-loop.h b/testsuite/module-playground/mod-loop.h
new file mode 100644
index 0000000..b9f5e82
--- /dev/null
+++ b/testsuite/module-playground/mod-loop.h
@@ -0,0 +1,13 @@
+#pragma once
+
+void printA(void);
+void printB(void);
+void printC(void);
+void printD(void);
+void printE(void);
+void printF(void);
+void printG(void);
+void printH(void);
+void printI(void);
+void printJ(void);
+void printK(void);
diff --git a/testsuite/module-playground/mod-simple-i386.ko b/testsuite/module-playground/mod-simple-i386.ko
new file mode 100644
index 0000000..9bce6e0
--- /dev/null
+++ b/testsuite/module-playground/mod-simple-i386.ko
Binary files differ
diff --git a/testsuite/module-playground/mod-simple-sparc64.ko b/testsuite/module-playground/mod-simple-sparc64.ko
new file mode 100644
index 0000000..17242c8
--- /dev/null
+++ b/testsuite/module-playground/mod-simple-sparc64.ko
Binary files differ
diff --git a/testsuite/module-playground/mod-simple-x86_64.ko b/testsuite/module-playground/mod-simple-x86_64.ko
new file mode 100644
index 0000000..0159b99
--- /dev/null
+++ b/testsuite/module-playground/mod-simple-x86_64.ko
Binary files differ
diff --git a/testsuite/module-playground/mod-simple.c b/testsuite/module-playground/mod-simple.c
new file mode 100644
index 0000000..503e4d8
--- /dev/null
+++ b/testsuite/module-playground/mod-simple.c
@@ -0,0 +1,32 @@
+#include <linux/debugfs.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+static struct dentry *debugfs_dir;
+
+static int test_show(struct seq_file *s, void *data)
+{
+ seq_puts(s, "test");
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(test);
+
+static int __init test_module_init(void)
+{
+ debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, NULL);
+ debugfs_create_file("test", 0444, debugfs_dir, NULL, &test_fops);
+
+ return 0;
+}
+
+static void test_module_exit(void)
+{
+ debugfs_remove_recursive(debugfs_dir);
+}
+
+module_init(test_module_init);
+module_exit(test_module_exit);
+
+MODULE_AUTHOR("Lucas De Marchi <lucas.demarchi@intel.com>");
+MODULE_LICENSE("GPL");
diff --git a/testsuite/path.c b/testsuite/path.c
new file mode 100644
index 0000000..5a291b1
--- /dev/null
+++ b/testsuite/path.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2012-2013 ProFUSION embedded systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* We unset _FILE_OFFSET_BITS here so we can override both stat and stat64 on
+ * 32-bit architectures and forward each to the right libc function */
+#undef _FILE_OFFSET_BITS
+
+#include <assert.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <shared/util.h>
+
+#include "testsuite.h"
+
+static void *nextlib;
+static const char *rootpath;
+static size_t rootpathlen;
+
+static inline bool need_trap(const char *path)
+{
+ return path != NULL && path[0] == '/'
+ && !strstartswith(path, ABS_TOP_BUILDDIR);
+}
+
+static const char *trap_path(const char *path, char buf[PATH_MAX * 2])
+{
+ size_t len;
+
+ if (!need_trap(path))
+ return path;
+
+ len = strlen(path);
+
+ if (len + rootpathlen > PATH_MAX * 2) {
+ errno = ENAMETOOLONG;
+ return NULL;
+ }
+
+ memcpy(buf, rootpath, rootpathlen);
+ strcpy(buf + rootpathlen, path);
+ return buf;
+}
+
+static bool get_rootpath(const char *f)
+{
+ if (rootpath != NULL)
+ return true;
+
+ rootpath = getenv(S_TC_ROOTFS);
+ if (rootpath == NULL) {
+ ERR("TRAP %s(): missing export %s?\n", f, S_TC_ROOTFS);
+ errno = ENOENT;
+ return false;
+ }
+
+ rootpathlen = strlen(rootpath);
+
+ return true;
+}
+
+static void *get_libc_func(const char *f)
+{
+ void *fp;
+
+ if (nextlib == NULL) {
+#ifdef RTLD_NEXT
+ nextlib = RTLD_NEXT;
+#else
+ nextlib = dlopen("libc.so.6", RTLD_LAZY);
+#endif
+ }
+
+ fp = dlsym(nextlib, f);
+ assert(fp);
+
+ return fp;
+}
+
+/* wrapper template for a function with one "const char* path" argument */
+#define WRAP_1ARG(rettype, failret, name) \
+TS_EXPORT rettype name(const char *path) \
+{ \
+ const char *p; \
+ char buf[PATH_MAX * 2]; \
+ static rettype (*_fn)(const char*); \
+ \
+ if (!get_rootpath(__func__)) \
+ return failret; \
+ _fn = get_libc_func(#name); \
+ p = trap_path(path, buf); \
+ if (p == NULL) \
+ return failret; \
+ return (*_fn)(p); \
+}
+
+/* wrapper template for a function with "const char* path" and another argument */
+#define WRAP_2ARGS(rettype, failret, name, arg2t) \
+TS_EXPORT rettype name(const char *path, arg2t arg2) \
+{ \
+ const char *p; \
+ char buf[PATH_MAX * 2]; \
+ static rettype (*_fn)(const char*, arg2t arg2); \
+ \
+ if (!get_rootpath(__func__)) \
+ return failret; \
+ _fn = get_libc_func(#name); \
+ p = trap_path(path, buf); \
+ if (p == NULL) \
+ return failret; \
+ return (*_fn)(p, arg2); \
+}
+
+/* wrapper template for open family */
+#define WRAP_OPEN(suffix) \
+TS_EXPORT int open ## suffix (const char *path, int flags, ...) \
+{ \
+ const char *p; \
+ char buf[PATH_MAX * 2]; \
+ static int (*_fn)(const char *path, int flags, ...); \
+ \
+ if (!get_rootpath(__func__)) \
+ return -1; \
+ _fn = get_libc_func("open" #suffix); \
+ p = trap_path(path, buf); \
+ if (p == NULL) \
+ return -1; \
+ \
+ if (flags & O_CREAT) { \
+ mode_t mode; \
+ va_list ap; \
+ \
+ va_start(ap, flags); \
+ mode = va_arg(ap, mode_t); \
+ va_end(ap); \
+ return _fn(p, flags, mode); \
+ } \
+ \
+ return _fn(p, flags); \
+}
+
+/*
+ * wrapper template for __xstat family
+ * This family got deprecated/dropped in glibc 2.32.9000, but we still need
+ * to keep it for a while for programs that were built against previous versions
+ */
+#define WRAP_VERSTAT(prefix, suffix) \
+TS_EXPORT int prefix ## stat ## suffix (int ver, \
+ const char *path, \
+ struct stat ## suffix *st); \
+TS_EXPORT int prefix ## stat ## suffix (int ver, \
+ const char *path, \
+ struct stat ## suffix *st) \
+{ \
+ const char *p; \
+ char buf[PATH_MAX * 2]; \
+ static int (*_fn)(int ver, const char *path, \
+ struct stat ## suffix *); \
+ _fn = get_libc_func(#prefix "stat" #suffix); \
+ \
+ if (!get_rootpath(__func__)) \
+ return -1; \
+ p = trap_path(path, buf); \
+ if (p == NULL) \
+ return -1; \
+ \
+ return _fn(ver, p, st); \
+}
+
+WRAP_1ARG(DIR*, NULL, opendir);
+WRAP_1ARG(int, -1, chdir);
+
+WRAP_2ARGS(FILE*, NULL, fopen, const char*);
+WRAP_2ARGS(FILE*, NULL, fopen64, const char*);
+WRAP_2ARGS(int, -1, mkdir, mode_t);
+WRAP_2ARGS(int, -1, access, int);
+WRAP_2ARGS(int, -1, stat, struct stat*);
+WRAP_2ARGS(int, -1, lstat, struct stat*);
+WRAP_2ARGS(int, -1, stat64, struct stat64*);
+WRAP_2ARGS(int, -1, lstat64, struct stat64*);
+WRAP_OPEN(64);
+
+WRAP_OPEN();
+
+#ifdef HAVE___XSTAT
+WRAP_VERSTAT(__x,);
+WRAP_VERSTAT(__lx,);
+WRAP_VERSTAT(__x,64);
+WRAP_VERSTAT(__lx,64);
+#endif
diff --git a/testsuite/rootfs-pristine/test-blacklist/etc/modprobe.d/modprobe.conf b/testsuite/rootfs-pristine/test-blacklist/etc/modprobe.d/modprobe.conf
new file mode 100644
index 0000000..126612f
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-blacklist/etc/modprobe.d/modprobe.conf
@@ -0,0 +1,2 @@
+blacklist floppy
+blacklist pcspkr
diff --git a/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.alias b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.alias.bin b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.builtin b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.builtin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.builtin
diff --git a/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.builtin.bin b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.builtin.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.builtin.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.dep b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.dep
new file mode 100644
index 0000000..d9ebfa3
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.dep
@@ -0,0 +1,4 @@
+kernel/fs/foo/mod-foo-b.ko:
+kernel/mod-foo-c.ko:
+kernel/lib/mod-foo-a.ko:
+kernel/fs/mod-foo.ko: kernel/fs/foo/mod-foo-b.ko kernel/lib/mod-foo-a.ko kernel/mod-foo-c.ko
diff --git a/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.dep.bin b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.dep.bin
new file mode 100644
index 0000000..8874801
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.devname b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.devname
new file mode 100644
index 0000000..58f6d6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.devname
@@ -0,0 +1 @@
+# Device nodes to trigger on-demand module loading.
diff --git a/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.order b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.order
new file mode 100644
index 0000000..85f2778
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.order
@@ -0,0 +1,7 @@
+kernel/fs/mbcache.ko
+kernel/fs/ext3/ext3.ko
+kernel/fs/ext2/ext2.ko
+kernel/fs/ext4/ext4.ko
+kernel/fs/jbd/jbd.ko
+kernel/fs/jbd2/jbd2.ko
+kernel/lib/crc16.ko
diff --git a/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.softdep b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.symbols b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.symbols
new file mode 100644
index 0000000..ddb6ab6
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.symbols
@@ -0,0 +1,4 @@
+# Aliases for symbols, used by symbol_request().
+alias symbol:print_fooA mod_foo_a
+alias symbol:print_fooC mod_foo_c
+alias symbol:print_fooB mod_foo_b
diff --git a/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.symbols.bin b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.symbols.bin
new file mode 100644
index 0000000..1add6e5
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-dependencies/lib/modules/4.0.20-kmod/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-depmod/detect-loop/correct.txt b/testsuite/rootfs-pristine/test-depmod/detect-loop/correct.txt
new file mode 100644
index 0000000..ff28545
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/detect-loop/correct.txt
@@ -0,0 +1,5 @@
+depmod: ERROR: Cycle detected: mod_loop_d -> mod_loop_e -> mod_loop_d
+depmod: ERROR: Cycle detected: mod_loop_i -> mod_loop_j -> mod_loop_k -> mod_loop_h -> mod_loop_i
+depmod: ERROR: Cycle detected: mod_loop_i -> mod_loop_j -> mod_loop_h -> mod_loop_i
+depmod: ERROR: Cycle detected: mod_loop_c -> mod_loop_a -> mod_loop_b -> mod_loop_c
+depmod: ERROR: Found 9 modules in dependency cycles!
diff --git a/testsuite/rootfs-pristine/test-depmod/detect-loop/lib/modules/4.4.4/modules.order b/testsuite/rootfs-pristine/test-depmod/detect-loop/lib/modules/4.4.4/modules.order
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/detect-loop/lib/modules/4.4.4/modules.order
diff --git a/testsuite/rootfs-pristine/test-depmod/modules-order-compressed/lib/modules/4.4.4/correct-modules.alias b/testsuite/rootfs-pristine/test-depmod/modules-order-compressed/lib/modules/4.4.4/correct-modules.alias
new file mode 100644
index 0000000..5675329
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/modules-order-compressed/lib/modules/4.4.4/correct-modules.alias
@@ -0,0 +1,37 @@
+# Aliases extracted from modules themselves.
+alias pci:v0000103Cd00003230sv0000103Csd0000323Dbc*sc*i* cciss
+alias pci:v0000103Cd00003230sv0000103Csd00003237bc*sc*i* cciss
+alias pci:v0000103Cd00003238sv0000103Csd00003215bc*sc*i* cciss
+alias pci:v0000103Cd00003238sv0000103Csd00003214bc*sc*i* cciss
+alias pci:v0000103Cd00003238sv0000103Csd00003213bc*sc*i* cciss
+alias pci:v0000103Cd00003238sv0000103Csd00003212bc*sc*i* cciss
+alias pci:v0000103Cd00003238sv0000103Csd00003211bc*sc*i* cciss
+alias pci:v0000103Cd00003230sv0000103Csd00003235bc*sc*i* cciss
+alias pci:v0000103Cd00003230sv0000103Csd00003234bc*sc*i* cciss
+alias pci:v0000103Cd00003230sv0000103Csd00003223bc*sc*i* cciss
+alias pci:v0000103Cd00003220sv0000103Csd00003225bc*sc*i* cciss
+alias pci:v00000E11d00000046sv00000E11sd0000409Dbc*sc*i* cciss
+alias pci:v00000E11d00000046sv00000E11sd0000409Cbc*sc*i* cciss
+alias pci:v00000E11d00000046sv00000E11sd0000409Bbc*sc*i* cciss
+alias pci:v00000E11d00000046sv00000E11sd0000409Abc*sc*i* cciss
+alias pci:v00000E11d00000046sv00000E11sd00004091bc*sc*i* cciss
+alias pci:v00000E11d0000B178sv00000E11sd00004083bc*sc*i* cciss
+alias pci:v00000E11d0000B178sv00000E11sd00004082bc*sc*i* cciss
+alias pci:v00000E11d0000B178sv00000E11sd00004080bc*sc*i* cciss
+alias pci:v00000E11d0000B060sv00000E11sd00004070bc*sc*i* cciss
+alias pci:v0000103Cd*sv*sd*bc01sc04i* hpsa
+alias pci:v0000103Cd0000323Bsv0000103Csd00003356bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Bsv0000103Csd00003355bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Bsv0000103Csd00003354bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Bsv0000103Csd00003353bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Bsv0000103Csd00003352bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Bsv0000103Csd00003351bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Bsv0000103Csd00003350bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Asv0000103Csd00003233bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Asv0000103Csd0000324Bbc*sc*i* hpsa
+alias pci:v0000103Cd0000323Asv0000103Csd0000324Abc*sc*i* hpsa
+alias pci:v0000103Cd0000323Asv0000103Csd00003249bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Asv0000103Csd00003247bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Asv0000103Csd00003245bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Asv0000103Csd00003243bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Asv0000103Csd00003241bc*sc*i* hpsa
diff --git a/testsuite/rootfs-pristine/test-depmod/modules-order-compressed/lib/modules/4.4.4/modules.builtin b/testsuite/rootfs-pristine/test-depmod/modules-order-compressed/lib/modules/4.4.4/modules.builtin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/modules-order-compressed/lib/modules/4.4.4/modules.builtin
diff --git a/testsuite/rootfs-pristine/test-depmod/modules-order-compressed/lib/modules/4.4.4/modules.order b/testsuite/rootfs-pristine/test-depmod/modules-order-compressed/lib/modules/4.4.4/modules.order
new file mode 100644
index 0000000..4b64309
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/modules-order-compressed/lib/modules/4.4.4/modules.order
@@ -0,0 +1,7 @@
+#336
+kernel/drivers/block/cciss.ko
+#2094
+kernel/drivers/scsi/scsi_mod.ko
+#2137
+kernel/drivers/scsi/hpsa.ko
+
diff --git a/testsuite/rootfs-pristine/test-depmod/modules-outdir/correct-modules.alias b/testsuite/rootfs-pristine/test-depmod/modules-outdir/correct-modules.alias
new file mode 100644
index 0000000..5675329
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/modules-outdir/correct-modules.alias
@@ -0,0 +1,37 @@
+# Aliases extracted from modules themselves.
+alias pci:v0000103Cd00003230sv0000103Csd0000323Dbc*sc*i* cciss
+alias pci:v0000103Cd00003230sv0000103Csd00003237bc*sc*i* cciss
+alias pci:v0000103Cd00003238sv0000103Csd00003215bc*sc*i* cciss
+alias pci:v0000103Cd00003238sv0000103Csd00003214bc*sc*i* cciss
+alias pci:v0000103Cd00003238sv0000103Csd00003213bc*sc*i* cciss
+alias pci:v0000103Cd00003238sv0000103Csd00003212bc*sc*i* cciss
+alias pci:v0000103Cd00003238sv0000103Csd00003211bc*sc*i* cciss
+alias pci:v0000103Cd00003230sv0000103Csd00003235bc*sc*i* cciss
+alias pci:v0000103Cd00003230sv0000103Csd00003234bc*sc*i* cciss
+alias pci:v0000103Cd00003230sv0000103Csd00003223bc*sc*i* cciss
+alias pci:v0000103Cd00003220sv0000103Csd00003225bc*sc*i* cciss
+alias pci:v00000E11d00000046sv00000E11sd0000409Dbc*sc*i* cciss
+alias pci:v00000E11d00000046sv00000E11sd0000409Cbc*sc*i* cciss
+alias pci:v00000E11d00000046sv00000E11sd0000409Bbc*sc*i* cciss
+alias pci:v00000E11d00000046sv00000E11sd0000409Abc*sc*i* cciss
+alias pci:v00000E11d00000046sv00000E11sd00004091bc*sc*i* cciss
+alias pci:v00000E11d0000B178sv00000E11sd00004083bc*sc*i* cciss
+alias pci:v00000E11d0000B178sv00000E11sd00004082bc*sc*i* cciss
+alias pci:v00000E11d0000B178sv00000E11sd00004080bc*sc*i* cciss
+alias pci:v00000E11d0000B060sv00000E11sd00004070bc*sc*i* cciss
+alias pci:v0000103Cd*sv*sd*bc01sc04i* hpsa
+alias pci:v0000103Cd0000323Bsv0000103Csd00003356bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Bsv0000103Csd00003355bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Bsv0000103Csd00003354bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Bsv0000103Csd00003353bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Bsv0000103Csd00003352bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Bsv0000103Csd00003351bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Bsv0000103Csd00003350bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Asv0000103Csd00003233bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Asv0000103Csd0000324Bbc*sc*i* hpsa
+alias pci:v0000103Cd0000323Asv0000103Csd0000324Abc*sc*i* hpsa
+alias pci:v0000103Cd0000323Asv0000103Csd00003249bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Asv0000103Csd00003247bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Asv0000103Csd00003245bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Asv0000103Csd00003243bc*sc*i* hpsa
+alias pci:v0000103Cd0000323Asv0000103Csd00003241bc*sc*i* hpsa
diff --git a/testsuite/rootfs-pristine/test-depmod/modules-outdir/correct-modules.dep b/testsuite/rootfs-pristine/test-depmod/modules-outdir/correct-modules.dep
new file mode 100644
index 0000000..ec50ac3
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/modules-outdir/correct-modules.dep
@@ -0,0 +1,3 @@
+kernel/drivers/block/cciss.ko:
+kernel/drivers/scsi/scsi_mod.ko:
+kernel/drivers/scsi/hpsa.ko: kernel/drivers/scsi/scsi_mod.ko
diff --git a/testsuite/rootfs-pristine/test-depmod/modules-outdir/lib/modules/4.4.4/modules.builtin b/testsuite/rootfs-pristine/test-depmod/modules-outdir/lib/modules/4.4.4/modules.builtin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/modules-outdir/lib/modules/4.4.4/modules.builtin
diff --git a/testsuite/rootfs-pristine/test-depmod/modules-outdir/lib/modules/4.4.4/modules.order b/testsuite/rootfs-pristine/test-depmod/modules-outdir/lib/modules/4.4.4/modules.order
new file mode 100644
index 0000000..4b64309
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/modules-outdir/lib/modules/4.4.4/modules.order
@@ -0,0 +1,7 @@
+#336
+kernel/drivers/block/cciss.ko
+#2094
+kernel/drivers/scsi/scsi_mod.ko
+#2137
+kernel/drivers/scsi/hpsa.ko
+
diff --git a/testsuite/rootfs-pristine/test-depmod/search-order-external-first/etc/depmod.d/external.conf b/testsuite/rootfs-pristine/test-depmod/search-order-external-first/etc/depmod.d/external.conf
new file mode 100644
index 0000000..59f46ae
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/search-order-external-first/etc/depmod.d/external.conf
@@ -0,0 +1 @@
+external 4\.4\..* /lib/modules/external
diff --git a/testsuite/rootfs-pristine/test-depmod/search-order-external-first/etc/depmod.d/search.conf b/testsuite/rootfs-pristine/test-depmod/search-order-external-first/etc/depmod.d/search.conf
new file mode 100644
index 0000000..642e497
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/search-order-external-first/etc/depmod.d/search.conf
@@ -0,0 +1 @@
+search external foobar foo built-in
diff --git a/testsuite/rootfs-pristine/test-depmod/search-order-external-first/lib/modules/4.4.4/correct-modules.dep b/testsuite/rootfs-pristine/test-depmod/search-order-external-first/lib/modules/4.4.4/correct-modules.dep
new file mode 100644
index 0000000..e612900
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/search-order-external-first/lib/modules/4.4.4/correct-modules.dep
@@ -0,0 +1 @@
+/lib/modules/external/mod-simple.ko:
diff --git a/testsuite/rootfs-pristine/test-depmod/search-order-external-last/etc/depmod.d/external.conf b/testsuite/rootfs-pristine/test-depmod/search-order-external-last/etc/depmod.d/external.conf
new file mode 100644
index 0000000..59f46ae
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/search-order-external-last/etc/depmod.d/external.conf
@@ -0,0 +1 @@
+external 4\.4\..* /lib/modules/external
diff --git a/testsuite/rootfs-pristine/test-depmod/search-order-external-last/etc/depmod.d/search.conf b/testsuite/rootfs-pristine/test-depmod/search-order-external-last/etc/depmod.d/search.conf
new file mode 100644
index 0000000..5fdb812
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/search-order-external-last/etc/depmod.d/search.conf
@@ -0,0 +1 @@
+search foobar foo built-in external
diff --git a/testsuite/rootfs-pristine/test-depmod/search-order-external-last/lib/modules/4.4.4/correct-modules.dep b/testsuite/rootfs-pristine/test-depmod/search-order-external-last/lib/modules/4.4.4/correct-modules.dep
new file mode 100644
index 0000000..eab3bb0
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/search-order-external-last/lib/modules/4.4.4/correct-modules.dep
@@ -0,0 +1 @@
+foobar/mod-simple.ko:
diff --git a/testsuite/rootfs-pristine/test-depmod/search-order-override/etc/depmod.d/override.conf b/testsuite/rootfs-pristine/test-depmod/search-order-override/etc/depmod.d/override.conf
new file mode 100644
index 0000000..fadf811
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/search-order-override/etc/depmod.d/override.conf
@@ -0,0 +1 @@
+override mod-simple 4.4.4 override
diff --git a/testsuite/rootfs-pristine/test-depmod/search-order-override/etc/depmod.d/search.conf b/testsuite/rootfs-pristine/test-depmod/search-order-override/etc/depmod.d/search.conf
new file mode 100644
index 0000000..289ddcd
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/search-order-override/etc/depmod.d/search.conf
@@ -0,0 +1 @@
+search foo built-in
diff --git a/testsuite/rootfs-pristine/test-depmod/search-order-override/lib/modules/4.4.4/correct-modules.dep b/testsuite/rootfs-pristine/test-depmod/search-order-override/lib/modules/4.4.4/correct-modules.dep
new file mode 100644
index 0000000..4c7ea8e
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/search-order-override/lib/modules/4.4.4/correct-modules.dep
@@ -0,0 +1 @@
+override/mod-simple.ko:
diff --git a/testsuite/rootfs-pristine/test-depmod/search-order-same-prefix/etc/depmod.d/search.conf b/testsuite/rootfs-pristine/test-depmod/search-order-same-prefix/etc/depmod.d/search.conf
new file mode 100644
index 0000000..d43973e
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/search-order-same-prefix/etc/depmod.d/search.conf
@@ -0,0 +1 @@
+search foobar foo built-in
diff --git a/testsuite/rootfs-pristine/test-depmod/search-order-same-prefix/lib/modules/4.4.4/correct-modules.dep b/testsuite/rootfs-pristine/test-depmod/search-order-same-prefix/lib/modules/4.4.4/correct-modules.dep
new file mode 100644
index 0000000..eab3bb0
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/search-order-same-prefix/lib/modules/4.4.4/correct-modules.dep
@@ -0,0 +1 @@
+foobar/mod-simple.ko:
diff --git a/testsuite/rootfs-pristine/test-depmod/search-order-simple/etc/depmod.d/search.conf b/testsuite/rootfs-pristine/test-depmod/search-order-simple/etc/depmod.d/search.conf
new file mode 100644
index 0000000..d17cafd
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/search-order-simple/etc/depmod.d/search.conf
@@ -0,0 +1 @@
+search updates built-in
diff --git a/testsuite/rootfs-pristine/test-depmod/search-order-simple/lib/modules/4.4.4/correct-modules.dep b/testsuite/rootfs-pristine/test-depmod/search-order-simple/lib/modules/4.4.4/correct-modules.dep
new file mode 100644
index 0000000..c5bba99
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-depmod/search-order-simple/lib/modules/4.4.4/correct-modules.dep
@@ -0,0 +1 @@
+updates/mod-simple.ko:
diff --git a/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.alias b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.alias.bin b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.builtin b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.builtin
new file mode 100644
index 0000000..1cbec61
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.builtin
@@ -0,0 +1 @@
+kernel/fake_builtin.ko
diff --git a/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.builtin.alias.bin b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.builtin.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.builtin.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.builtin.bin b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.builtin.bin
new file mode 100644
index 0000000..0423f03
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.builtin.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.dep b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.dep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.dep
diff --git a/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.dep.bin b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.dep.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.devname b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.devname
new file mode 100644
index 0000000..58f6d6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.devname
@@ -0,0 +1 @@
+# Device nodes to trigger on-demand module loading.
diff --git a/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.softdep b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.symbols b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.symbols
new file mode 100644
index 0000000..618c345
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.symbols
@@ -0,0 +1 @@
+# Aliases for symbols, used by symbol_request().
diff --git a/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.symbols.bin b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.symbols.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources-empty-builtin-aliases-bin/lib/modules/5.6.0/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.alias b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.alias.bin b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.builtin b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.builtin
new file mode 100644
index 0000000..1cbec61
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.builtin
@@ -0,0 +1 @@
+kernel/fake_builtin.ko
diff --git a/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.builtin.bin b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.builtin.bin
new file mode 100644
index 0000000..0423f03
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.builtin.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.dep b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.dep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.dep
diff --git a/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.dep.bin b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.dep.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.devname b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.devname
new file mode 100644
index 0000000..58f6d6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.devname
@@ -0,0 +1 @@
+# Device nodes to trigger on-demand module loading.
diff --git a/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.softdep b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.symbols b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.symbols
new file mode 100644
index 0000000..618c345
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.symbols
@@ -0,0 +1 @@
+# Aliases for symbols, used by symbol_request().
diff --git a/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.symbols.bin b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.symbols.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-init-load-resources/lib/modules/5.6.0/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.alias b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.alias.bin b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.builtin b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.builtin
new file mode 100644
index 0000000..1cbec61
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.builtin
@@ -0,0 +1 @@
+kernel/fake_builtin.ko
diff --git a/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.builtin.bin b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.builtin.bin
new file mode 100644
index 0000000..0423f03
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.builtin.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.dep b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.dep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.dep
diff --git a/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.dep.bin b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.dep.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.devname b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.devname
new file mode 100644
index 0000000..58f6d6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.devname
@@ -0,0 +1 @@
+# Device nodes to trigger on-demand module loading.
diff --git a/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.softdep b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.symbols b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.symbols
new file mode 100644
index 0000000..618c345
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.symbols
@@ -0,0 +1 @@
+# Aliases for symbols, used by symbol_request().
diff --git a/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.symbols.bin b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.symbols.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-initstate/lib/modules/4.4.4/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-loaded/correct.txt b/testsuite/rootfs-pristine/test-loaded/correct.txt
new file mode 100644
index 0000000..71c5f7f
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/correct.txt
@@ -0,0 +1,2 @@
+Module Size Used by
+btusb 11216 0
diff --git a/testsuite/rootfs-pristine/test-loaded/proc/modules b/testsuite/rootfs-pristine/test-loaded/proc/modules
new file mode 100644
index 0000000..ce468c0
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/proc/modules
@@ -0,0 +1 @@
+btusb 11216 0 - Live 0xffffffffa014a000
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/drivers/usb:btusb b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/drivers/usb:btusb
new file mode 120000
index 0000000..c173837
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/drivers/usb:btusb
@@ -0,0 +1 @@
+../../../bus/usb/drivers/btusb \ No newline at end of file
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/holders/.gitignore b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/holders/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/holders/.gitignore
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/initstate b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/initstate
new file mode 100644
index 0000000..e23fe64
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/initstate
@@ -0,0 +1 @@
+live
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/notes/.note.gnu.build-id b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/notes/.note.gnu.build-id
new file mode 100644
index 0000000..0758558
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/notes/.note.gnu.build-id
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/disable_scofix b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/disable_scofix
new file mode 100644
index 0000000..d52e798
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/disable_scofix
@@ -0,0 +1 @@
+N
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/force_scofix b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/force_scofix
new file mode 100644
index 0000000..d52e798
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/force_scofix
@@ -0,0 +1 @@
+N
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/ignore_csr b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/ignore_csr
new file mode 100644
index 0000000..d52e798
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/ignore_csr
@@ -0,0 +1 @@
+N
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/ignore_dga b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/ignore_dga
new file mode 100644
index 0000000..d52e798
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/ignore_dga
@@ -0,0 +1 @@
+N
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/ignore_sniffer b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/ignore_sniffer
new file mode 100644
index 0000000..d52e798
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/ignore_sniffer
@@ -0,0 +1 @@
+N
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/reset b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/reset
new file mode 100644
index 0000000..9bda8c3
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/parameters/reset
@@ -0,0 +1 @@
+Y
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/refcnt b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/refcnt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/refcnt
@@ -0,0 +1 @@
+0
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.bss b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.bss
new file mode 100644
index 0000000..e971686
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.bss
@@ -0,0 +1 @@
+0xffffffffa014c828
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.data b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.data
new file mode 100644
index 0000000..5ccfa09
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.data
@@ -0,0 +1 @@
+0xffffffffa014c040
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.exit.text b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.exit.text
new file mode 100644
index 0000000..446df03
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.exit.text
@@ -0,0 +1 @@
+0xffffffffa014bd7c
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.gnu.linkonce.this_module b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.gnu.linkonce.this_module
new file mode 100644
index 0000000..f91a8fd
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.gnu.linkonce.this_module
@@ -0,0 +1 @@
+0xffffffffa014c600
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.init.text b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.init.text
new file mode 100644
index 0000000..1179bf2
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.init.text
@@ -0,0 +1 @@
+0xffffffffa014e000
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.note.gnu.build-id b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.note.gnu.build-id
new file mode 100644
index 0000000..e08ddab
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.note.gnu.build-id
@@ -0,0 +1 @@
+0xffffffffa014bd90
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.rodata b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.rodata
new file mode 100644
index 0000000..327441b
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.rodata
@@ -0,0 +1 @@
+0xffffffffa014bfe0
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.rodata.str1.1 b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.rodata.str1.1
new file mode 100644
index 0000000..e96b658
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.rodata.str1.1
@@ -0,0 +1 @@
+0xffffffffa014be29
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.rodata.str1.8 b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.rodata.str1.8
new file mode 100644
index 0000000..d437cbe
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.rodata.str1.8
@@ -0,0 +1 @@
+0xffffffffa014bdb8
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.smp_locks b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.smp_locks
new file mode 100644
index 0000000..955e243
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.smp_locks
@@ -0,0 +1 @@
+0xffffffffa014bea8
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.strtab b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.strtab
new file mode 100644
index 0000000..a874fed
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.strtab
@@ -0,0 +1 @@
+0xffffffffa014ede8
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.symtab b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.symtab
new file mode 100644
index 0000000..fafe019
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.symtab
@@ -0,0 +1 @@
+0xffffffffa014e020
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.text b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.text
new file mode 100644
index 0000000..0a967df
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/.text
@@ -0,0 +1 @@
+0xffffffffa014a000
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/__param b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/__param
new file mode 100644
index 0000000..9f6710a
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/sections/__param
@@ -0,0 +1 @@
+0xffffffffa014bf20
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/srcversion b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/srcversion
new file mode 100644
index 0000000..a688adf
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/srcversion
@@ -0,0 +1 @@
+8EEAC35838CCA1118F97F5F
diff --git a/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/version b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/version
new file mode 100644
index 0000000..5a2a580
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-loaded/sys/module/btusb/version
@@ -0,0 +1 @@
+0.6
diff --git a/testsuite/rootfs-pristine/test-modinfo/correct-author.txt b/testsuite/rootfs-pristine/test-modinfo/correct-author.txt
new file mode 100644
index 0000000..b74c9bf
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/correct-author.txt
@@ -0,0 +1,3 @@
+Lucas De Marchi <lucas.demarchi@intel.com>
+Lucas De Marchi <lucas.demarchi@intel.com>
+Lucas De Marchi <lucas.demarchi@intel.com>
diff --git a/testsuite/rootfs-pristine/test-modinfo/correct-depends.txt b/testsuite/rootfs-pristine/test-modinfo/correct-depends.txt
new file mode 100644
index 0000000..b28b04f
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/correct-depends.txt
@@ -0,0 +1,3 @@
+
+
+
diff --git a/testsuite/rootfs-pristine/test-modinfo/correct-description.txt b/testsuite/rootfs-pristine/test-modinfo/correct-description.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/correct-description.txt
diff --git a/testsuite/rootfs-pristine/test-modinfo/correct-external.txt b/testsuite/rootfs-pristine/test-modinfo/correct-external.txt
new file mode 100644
index 0000000..a094abe
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/correct-external.txt
@@ -0,0 +1 @@
+/lib/modules/external/mod-simple.ko
diff --git a/testsuite/rootfs-pristine/test-modinfo/correct-filename.txt b/testsuite/rootfs-pristine/test-modinfo/correct-filename.txt
new file mode 100644
index 0000000..bcd47c0
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/correct-filename.txt
@@ -0,0 +1,3 @@
+/mod-simple-i386.ko
+/mod-simple-x86_64.ko
+/mod-simple-sparc64.ko
diff --git a/testsuite/rootfs-pristine/test-modinfo/correct-license.txt b/testsuite/rootfs-pristine/test-modinfo/correct-license.txt
new file mode 100644
index 0000000..f79931d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/correct-license.txt
@@ -0,0 +1,4 @@
+LGPL
+LGPL
+LGPL
+
diff --git a/testsuite/rootfs-pristine/test-modinfo/correct-parm.txt b/testsuite/rootfs-pristine/test-modinfo/correct-parm.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/correct-parm.txt
diff --git a/testsuite/rootfs-pristine/test-modinfo/correct-sig_hashalgo-openssl.txt b/testsuite/rootfs-pristine/test-modinfo/correct-sig_hashalgo-openssl.txt
new file mode 100644
index 0000000..f97c4fa
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/correct-sig_hashalgo-openssl.txt
@@ -0,0 +1,3 @@
+sha1
+sha256
+sha256
diff --git a/testsuite/rootfs-pristine/test-modinfo/correct-sig_hashalgo.txt b/testsuite/rootfs-pristine/test-modinfo/correct-sig_hashalgo.txt
new file mode 100644
index 0000000..23cb933
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/correct-sig_hashalgo.txt
@@ -0,0 +1,4 @@
+sha1
+sha256
+unknown
+
diff --git a/testsuite/rootfs-pristine/test-modinfo/correct-sig_key-openssl.txt b/testsuite/rootfs-pristine/test-modinfo/correct-sig_key-openssl.txt
new file mode 100644
index 0000000..25a75a8
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/correct-sig_key-openssl.txt
@@ -0,0 +1,3 @@
+E3:C8:FC:A7:3F:B3:1D:DE:84:81:EF:38:E3:4C:DE:4B:0C:FD:1B:F9
+E3:C8:FC:A7:3F:B3:1D:DE:84:81:EF:38:E3:4C:DE:4B:0C:FD:1B:F9
+26:DA:C3:EB:0F:0D:1A:56:A2:D8:B2:13:F0:D7:53:47:1D:0D:48:68
diff --git a/testsuite/rootfs-pristine/test-modinfo/correct-sig_key.txt b/testsuite/rootfs-pristine/test-modinfo/correct-sig_key.txt
new file mode 100644
index 0000000..7dc4c6a
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/correct-sig_key.txt
@@ -0,0 +1,3 @@
+E3:C8:FC:A7:3F:B3:1D:DE:84:81:EF:38:E3:4C:DE:4B:0C:FD:1B:F9
+E3:C8:FC:A7:3F:B3:1D:DE:84:81:EF:38:E3:4C:DE:4B:0C:FD:1B:F9
+
diff --git a/testsuite/rootfs-pristine/test-modinfo/correct-signer-openssl.txt b/testsuite/rootfs-pristine/test-modinfo/correct-signer-openssl.txt
new file mode 100644
index 0000000..2b979f9
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/correct-signer-openssl.txt
@@ -0,0 +1,3 @@
+Magrathea: Glacier signing key
+Magrathea: Glacier signing key
+Build time autogenerated kernel key
diff --git a/testsuite/rootfs-pristine/test-modinfo/correct-signer.txt b/testsuite/rootfs-pristine/test-modinfo/correct-signer.txt
new file mode 100644
index 0000000..afe83df
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/correct-signer.txt
@@ -0,0 +1,3 @@
+Magrathea: Glacier signing key
+Magrathea: Glacier signing key
+
diff --git a/testsuite/rootfs-pristine/test-modinfo/correct.txt b/testsuite/rootfs-pristine/test-modinfo/correct.txt
new file mode 100644
index 0000000..92ff247
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/correct.txt
@@ -0,0 +1,24 @@
+filename: /ext4-x86_64-sha1.ko
+license: GPL
+description: Fourth Extended Filesystem
+author: Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others
+alias: ext3
+alias: ext2
+depends: mbcache,jbd2
+intree: Y
+vermagic: 3.7.0 SMP mod_unload
+signer: Magrathea: Glacier signing key
+sig_key: E3:C8:FC:A7:3F:B3:1D:DE:84:81:EF:38:E3:4C:DE:4B:0C:FD:1B:F9
+sig_hashalgo: sha1
+filename: /ext4-x86_64-sha256.ko
+license: GPL
+description: Fourth Extended Filesystem
+author: Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others
+alias: ext3
+alias: ext2
+depends: mbcache,jbd2
+intree: Y
+vermagic: 3.7.0 SMP mod_unload
+signer: Magrathea: Glacier signing key
+sig_key: E3:C8:FC:A7:3F:B3:1D:DE:84:81:EF:38:E3:4C:DE:4B:0C:FD:1B:F9
+sig_hashalgo: sha256
diff --git a/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.alias b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.alias.bin b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.builtin.bin b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.builtin.bin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.builtin.bin
diff --git a/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.dep b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.dep
new file mode 100644
index 0000000..e612900
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.dep
@@ -0,0 +1 @@
+/lib/modules/external/mod-simple.ko:
diff --git a/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.dep.bin b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.dep.bin
new file mode 100644
index 0000000..556e3c8
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.devname b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.devname
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.devname
diff --git a/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.softdep b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.symbols b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.symbols
new file mode 100644
index 0000000..618c345
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.symbols
@@ -0,0 +1 @@
+# Aliases for symbols, used by symbol_request().
diff --git a/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.symbols.bin b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.symbols.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modinfo/external/lib/modules/4.4.4/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/alias-to-none/correct.txt b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/correct.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/correct.txt
diff --git a/testsuite/rootfs-pristine/test-modprobe/alias-to-none/etc/modprobe.d/bogus.conf b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/etc/modprobe.d/bogus.conf
new file mode 100644
index 0000000..fe0d1b4
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/etc/modprobe.d/bogus.conf
@@ -0,0 +1 @@
+alias mod-simple deaddood
diff --git a/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.alias b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.alias.bin b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.builtin.bin b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.builtin.bin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.builtin.bin
diff --git a/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.dep b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.dep
new file mode 100644
index 0000000..5476653
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.dep
@@ -0,0 +1 @@
+kernel/mod-simple.ko:
diff --git a/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.dep.bin b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.dep.bin
new file mode 100644
index 0000000..b09a854
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.devname b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.devname
new file mode 100644
index 0000000..58f6d6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.devname
@@ -0,0 +1 @@
+# Device nodes to trigger on-demand module loading.
diff --git a/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.softdep b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.symbols b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.symbols
new file mode 100644
index 0000000..618c345
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.symbols
@@ -0,0 +1 @@
+# Aliases for symbols, used by symbol_request().
diff --git a/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.symbols.bin b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.symbols.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/lib/modules/4.4.4/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/alias-to-none/proc/modules b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/proc/modules
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/alias-to-none/proc/modules
diff --git a/testsuite/rootfs-pristine/test-modprobe/builtin/correct.txt b/testsuite/rootfs-pristine/test-modprobe/builtin/correct.txt
new file mode 100644
index 0000000..509143d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/builtin/correct.txt
@@ -0,0 +1 @@
+unix
diff --git a/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.alias b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.alias.bin b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.builtin b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.builtin
new file mode 100644
index 0000000..3c4ef2c
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.builtin
@@ -0,0 +1 @@
+kernel/net/unix/unix.ko
diff --git a/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.builtin.bin b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.builtin.bin
new file mode 100644
index 0000000..41af3ee
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.builtin.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.dep b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.dep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.dep
diff --git a/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.dep.bin b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.dep.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.devname b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.devname
new file mode 100644
index 0000000..58f6d6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.devname
@@ -0,0 +1 @@
+# Device nodes to trigger on-demand module loading.
diff --git a/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.softdep b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.softdep
new file mode 100644
index 0000000..3cc0512
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.softdep
@@ -0,0 +1,2 @@
+# Soft dependencies extracted from modules themselves.
+# Copy, with a .conf extension, to /etc/modprobe.d to use it with modprobe.
diff --git a/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.symbols b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.symbols
new file mode 100644
index 0000000..618c345
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.symbols
@@ -0,0 +1 @@
+# Aliases for symbols, used by symbol_request().
diff --git a/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.symbols.bin b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.symbols.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/builtin/lib/modules/4.4.4/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.alias b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.alias.bin b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.builtin.bin b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.builtin.bin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.builtin.bin
diff --git a/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.dep b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.dep
new file mode 100644
index 0000000..e612900
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.dep
@@ -0,0 +1 @@
+/lib/modules/external/mod-simple.ko:
diff --git a/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.dep.bin b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.dep.bin
new file mode 100644
index 0000000..556e3c8
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.devname b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.devname
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.devname
diff --git a/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.softdep b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.symbols b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.symbols
new file mode 100644
index 0000000..618c345
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.symbols
@@ -0,0 +1 @@
+# Aliases for symbols, used by symbol_request().
diff --git a/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.symbols.bin b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.symbols.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/external/lib/modules/4.4.4/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/external/proc/modules b/testsuite/rootfs-pristine/test-modprobe/external/proc/modules
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/external/proc/modules
diff --git a/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.alias b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.alias.bin b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.builtin.bin b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.builtin.bin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.builtin.bin
diff --git a/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.dep b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.dep
new file mode 100644
index 0000000..5476653
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.dep
@@ -0,0 +1 @@
+kernel/mod-simple.ko:
diff --git a/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.dep.bin b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.dep.bin
new file mode 100644
index 0000000..b09a854
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.devname b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.devname
new file mode 100644
index 0000000..58f6d6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.devname
@@ -0,0 +1 @@
+# Device nodes to trigger on-demand module loading.
diff --git a/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.softdep b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.symbols b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.symbols
new file mode 100644
index 0000000..618c345
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.symbols
@@ -0,0 +1 @@
+# Aliases for symbols, used by symbol_request().
diff --git a/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.symbols.bin b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.symbols.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/force/lib/modules/4.4.4/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/force/proc/modules b/testsuite/rootfs-pristine/test-modprobe/force/proc/modules
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/force/proc/modules
diff --git a/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/etc/modprobe.d/dumb-instal-loop.conf b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/etc/modprobe.d/dumb-instal-loop.conf
new file mode 100644
index 0000000..4ec3fbf
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/etc/modprobe.d/dumb-instal-loop.conf
@@ -0,0 +1 @@
+install mod-loop-b $MODPROBE --ignore-install mod-loop-b && { $MODPROBE --quiet mod-loop-a ; }
diff --git a/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.alias b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.alias.bin b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.builtin.bin b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.builtin.bin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.builtin.bin
diff --git a/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.dep b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.dep
new file mode 100644
index 0000000..869e6ea
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.dep
@@ -0,0 +1,2 @@
+kernel/mod-loop-b.ko:
+kernel/mod-loop-a.ko: kernel/mod-loop-b.ko
diff --git a/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.dep.bin b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.dep.bin
new file mode 100644
index 0000000..3d1b357
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.devname b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.devname
new file mode 100644
index 0000000..58f6d6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.devname
@@ -0,0 +1 @@
+# Device nodes to trigger on-demand module loading.
diff --git a/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.softdep b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.symbols b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.symbols
new file mode 100644
index 0000000..6c53580
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.symbols
@@ -0,0 +1,3 @@
+# Aliases for symbols, used by symbol_request().
+alias symbol:printB mod_loop_b
+alias symbol:printA mod_loop_a
diff --git a/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.symbols.bin b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.symbols.bin
new file mode 100644
index 0000000..7cb72ca
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/install-cmd-loop/lib/modules/4.4.4/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.alias b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.alias.bin b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.builtin.bin b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.builtin.bin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.builtin.bin
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.dep b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.dep
new file mode 100644
index 0000000..e612900
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.dep
@@ -0,0 +1 @@
+/lib/modules/external/mod-simple.ko:
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.dep.bin b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.dep.bin
new file mode 100644
index 0000000..556e3c8
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.devname b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.devname
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.devname
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.softdep b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.symbols b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.symbols
new file mode 100644
index 0000000..618c345
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.symbols
@@ -0,0 +1 @@
+# Aliases for symbols, used by symbol_request().
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.symbols.bin b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.symbols.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/lib/modules/4.4.4/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/proc/modules b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/proc/modules
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-abspath/proc/modules
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.alias b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.alias.bin b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.builtin.bin b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.builtin.bin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.builtin.bin
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.dep b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.dep
new file mode 100644
index 0000000..e612900
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.dep
@@ -0,0 +1 @@
+/lib/modules/external/mod-simple.ko:
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.dep.bin b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.dep.bin
new file mode 100644
index 0000000..556e3c8
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.devname b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.devname
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.devname
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.softdep b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.symbols b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.symbols
new file mode 100644
index 0000000..618c345
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.symbols
@@ -0,0 +1 @@
+# Aliases for symbols, used by symbol_request().
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.symbols.bin b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.symbols.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/lib/modules/4.4.4/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/proc/modules b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/proc/modules
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-from-relpath/proc/modules
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/correct.txt b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/correct.txt
new file mode 100644
index 0000000..0d50154
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/correct.txt
@@ -0,0 +1 @@
+insmod /lib/modules/4.4.4/kernel/mod-simple.ko foo bar=1
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.alias b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.alias.bin b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.builtin.bin b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.builtin.bin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.builtin.bin
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.dep b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.dep
new file mode 100644
index 0000000..5476653
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.dep
@@ -0,0 +1 @@
+kernel/mod-simple.ko:
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.dep.bin b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.dep.bin
new file mode 100644
index 0000000..b09a854
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.devname b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.devname
new file mode 100644
index 0000000..58f6d6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.devname
@@ -0,0 +1 @@
+# Device nodes to trigger on-demand module loading.
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.softdep b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.symbols b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.symbols
new file mode 100644
index 0000000..618c345
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.symbols
@@ -0,0 +1 @@
+# Aliases for symbols, used by symbol_request().
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.symbols.bin b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.symbols.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/lib/modules/4.4.4/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/proc/cmdline b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/proc/cmdline
new file mode 100644
index 0000000..cd3bacd
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/proc/cmdline
@@ -0,0 +1 @@
+initrd=\initramfs-linux.img mod_simple.foo mod_simple.bar=1 root=/dev/sda2 rootfstype=ext4 add_efi_memmap quiet rw
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/proc/modules b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/proc/modules
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline/proc/modules
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline2/correct.txt b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline2/correct.txt
new file mode 100644
index 0000000..b73a680
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline2/correct.txt
@@ -0,0 +1,5 @@
+options psmouse foo
+options psmouse bar=1
+
+# End of configuration files. Dumping indexes now:
+
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline2/proc/cmdline b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline2/proc/cmdline
new file mode 100644
index 0000000..f048fdd
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline2/proc/cmdline
@@ -0,0 +1 @@
+psmouse.foo psmouse.bar=1 quiet rw
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline3/correct.txt b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline3/correct.txt
new file mode 100644
index 0000000..b73a680
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline3/correct.txt
@@ -0,0 +1,5 @@
+options psmouse foo
+options psmouse bar=1
+
+# End of configuration files. Dumping indexes now:
+
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline3/proc/cmdline b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline3/proc/cmdline
new file mode 100644
index 0000000..3575bb1
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline3/proc/cmdline
@@ -0,0 +1 @@
+BOOT_IMAGE=/boot/vmlinuz-3.12.12-57.g5f654cf-default initrd=\initramfs-linux.img psmouse.foo psmouse.bar=1 root=/dev/sda2 rootfstype=ext4 add_efi_memmap quiet rw
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline4/correct.txt b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline4/correct.txt
new file mode 100644
index 0000000..60fa483
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline4/correct.txt
@@ -0,0 +1,4 @@
+options testmodule testparam=1.5G
+
+# End of configuration files. Dumping indexes now:
+
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline4/proc/cmdline b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline4/proc/cmdline
new file mode 100644
index 0000000..c460c5e
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline4/proc/cmdline
@@ -0,0 +1 @@
+testmodule.testparam=1.5G
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline5/correct.txt b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline5/correct.txt
new file mode 100644
index 0000000..6996ba2
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline5/correct.txt
@@ -0,0 +1,6 @@
+options psmouse foo
+options psmouse bar=1
+options psmouse foobar="test 1"
+
+# End of configuration files. Dumping indexes now:
+
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline5/proc/cmdline b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline5/proc/cmdline
new file mode 100644
index 0000000..84e0168
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline5/proc/cmdline
@@ -0,0 +1 @@
+psmouse.foo psmouse.bar=1 psmouse.foobar="test 1" psmouse."invalid option" " notamodule" "noteamodule2 " notamodule3 quiet rw
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline6/correct.txt b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline6/correct.txt
new file mode 100644
index 0000000..7a087ef
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline6/correct.txt
@@ -0,0 +1,6 @@
+options psmouse foo=2
+options psmouse bar=1
+options psmouse zinga=test
+
+# End of configuration files. Dumping indexes now:
+
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline6/proc/cmdline b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline6/proc/cmdline
new file mode 100644
index 0000000..14bbd2e
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline6/proc/cmdline
@@ -0,0 +1 @@
+psmouse.foo=2 ivrs_acpihid[14:00.5]=AMD0020:00 psmouse.bar=1 psmouse.zinga=test
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/correct.txt b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/correct.txt
new file mode 100644
index 0000000..d80da6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/correct.txt
@@ -0,0 +1,5 @@
+options psmouse foo
+options parport dyndbg="file drivers/parport/ieee1284_ops.c +mpf"
+
+# End of configuration files. Dumping indexes now:
+
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/module-param-kcmdline7/correct.txt b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/module-param-kcmdline7/correct.txt
new file mode 100644
index 0000000..d80da6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/module-param-kcmdline7/correct.txt
@@ -0,0 +1,5 @@
+options psmouse foo
+options parport dyndbg="file drivers/parport/ieee1284_ops.c +mpf"
+
+# End of configuration files. Dumping indexes now:
+
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/module-param-kcmdline7/proc/cmdline b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/module-param-kcmdline7/proc/cmdline
new file mode 100644
index 0000000..86f9052
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/module-param-kcmdline7/proc/cmdline
@@ -0,0 +1 @@
+psmouse.foo parport.dyndbg="file drivers/parport/ieee1284_ops.c +mpf" quiet rw
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/proc/cmdline b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/proc/cmdline
new file mode 100644
index 0000000..86f9052
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline7/proc/cmdline
@@ -0,0 +1 @@
+psmouse.foo parport.dyndbg="file drivers/parport/ieee1284_ops.c +mpf" quiet rw
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/correct.txt b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/correct.txt
new file mode 100644
index 0000000..d80da6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/correct.txt
@@ -0,0 +1,5 @@
+options psmouse foo
+options parport dyndbg="file drivers/parport/ieee1284_ops.c +mpf"
+
+# End of configuration files. Dumping indexes now:
+
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/module-param-kcmdline7/correct.txt b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/module-param-kcmdline7/correct.txt
new file mode 100644
index 0000000..d80da6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/module-param-kcmdline7/correct.txt
@@ -0,0 +1,5 @@
+options psmouse foo
+options parport dyndbg="file drivers/parport/ieee1284_ops.c +mpf"
+
+# End of configuration files. Dumping indexes now:
+
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/module-param-kcmdline7/proc/cmdline b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/module-param-kcmdline7/proc/cmdline
new file mode 100644
index 0000000..86f9052
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/module-param-kcmdline7/proc/cmdline
@@ -0,0 +1 @@
+psmouse.foo parport.dyndbg="file drivers/parport/ieee1284_ops.c +mpf" quiet rw
diff --git a/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/proc/cmdline b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/proc/cmdline
new file mode 100644
index 0000000..eab04ad
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/module-param-kcmdline8/proc/cmdline
@@ -0,0 +1 @@
+psmouse.foo "parport.dyndbg=file drivers/parport/ieee1284_ops.c +mpf" quiet rw
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.alias b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.alias.bin b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.builtin.bin b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.builtin.bin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.builtin.bin
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.dep b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.dep
new file mode 100644
index 0000000..5476653
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.dep
@@ -0,0 +1 @@
+kernel/mod-simple.ko:
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.dep.bin b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.dep.bin
new file mode 100644
index 0000000..b09a854
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.devname b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.devname
new file mode 100644
index 0000000..58f6d6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.devname
@@ -0,0 +1 @@
+# Device nodes to trigger on-demand module loading.
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.softdep b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.symbols b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.symbols
new file mode 100644
index 0000000..618c345
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.symbols
@@ -0,0 +1 @@
+# Aliases for symbols, used by symbol_request().
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.symbols.bin b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.symbols.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/lib/modules/3.3.3/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/proc/modules b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/proc/modules
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel-force/proc/modules
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.alias b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.alias.bin b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.builtin.bin b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.builtin.bin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.builtin.bin
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.dep b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.dep
new file mode 100644
index 0000000..5476653
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.dep
@@ -0,0 +1 @@
+kernel/mod-simple.ko:
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.dep.bin b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.dep.bin
new file mode 100644
index 0000000..b09a854
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.devname b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.devname
new file mode 100644
index 0000000..58f6d6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.devname
@@ -0,0 +1 @@
+# Device nodes to trigger on-demand module loading.
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.softdep b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.symbols b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.symbols
new file mode 100644
index 0000000..618c345
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.symbols
@@ -0,0 +1 @@
+# Aliases for symbols, used by symbol_request().
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.symbols.bin b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.symbols.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel/lib/modules/3.3.3/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/oldkernel/proc/modules b/testsuite/rootfs-pristine/test-modprobe/oldkernel/proc/modules
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/oldkernel/proc/modules
diff --git a/testsuite/rootfs-pristine/test-modprobe/show-depends/correct-mod-simple.txt b/testsuite/rootfs-pristine/test-modprobe/show-depends/correct-mod-simple.txt
new file mode 100644
index 0000000..5426b9b
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/show-depends/correct-mod-simple.txt
@@ -0,0 +1 @@
+insmod /lib/modules/4.4.4/kernel/mod-simple.ko
diff --git a/testsuite/rootfs-pristine/test-modprobe/show-depends/correct.txt b/testsuite/rootfs-pristine/test-modprobe/show-depends/correct.txt
new file mode 100644
index 0000000..38d6d97
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/show-depends/correct.txt
@@ -0,0 +1,2 @@
+insmod /lib/modules/4.4.4/kernel/mod-loop-b.ko
+insmod /lib/modules/4.4.4/kernel/mod-loop-a.ko
diff --git a/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.alias b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.alias.bin b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.builtin.bin b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.builtin.bin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.builtin.bin
diff --git a/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.dep b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.dep
new file mode 100644
index 0000000..f166f66
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.dep
@@ -0,0 +1,3 @@
+kernel/mod-simple.ko:
+kernel/mod-loop-b.ko:
+kernel/mod-loop-a.ko: kernel/mod-loop-b.ko
diff --git a/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.dep.bin b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.dep.bin
new file mode 100644
index 0000000..418d583
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.devname b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.devname
new file mode 100644
index 0000000..58f6d6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.devname
@@ -0,0 +1 @@
+# Device nodes to trigger on-demand module loading.
diff --git a/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.softdep b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.symbols b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.symbols
new file mode 100644
index 0000000..6c53580
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.symbols
@@ -0,0 +1,3 @@
+# Aliases for symbols, used by symbol_request().
+alias symbol:printB mod_loop_b
+alias symbol:printA mod_loop_a
diff --git a/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.symbols.bin b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.symbols.bin
new file mode 100644
index 0000000..27c5f43
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/show-depends/lib/modules/4.4.4/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/show-depends/proc/modules b/testsuite/rootfs-pristine/test-modprobe/show-depends/proc/modules
new file mode 100644
index 0000000..aab95dd
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/show-depends/proc/modules
@@ -0,0 +1,2 @@
+btusb 11911 0 - Live 0xffffffffa00ec000
+bluetooth 173424 1 btusb, Live 0xffffffffa0040000
diff --git a/testsuite/rootfs-pristine/test-modprobe/show-depends/sys/module/mod_loop_a/initstate b/testsuite/rootfs-pristine/test-modprobe/show-depends/sys/module/mod_loop_a/initstate
new file mode 100644
index 0000000..e23fe64
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/show-depends/sys/module/mod_loop_a/initstate
@@ -0,0 +1 @@
+live
diff --git a/testsuite/rootfs-pristine/test-modprobe/show-depends/sys/module/mod_loop_b/initstate b/testsuite/rootfs-pristine/test-modprobe/show-depends/sys/module/mod_loop_b/initstate
new file mode 100644
index 0000000..e23fe64
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/show-depends/sys/module/mod_loop_b/initstate
@@ -0,0 +1 @@
+live
diff --git a/testsuite/rootfs-pristine/test-modprobe/show-exports/correct.txt b/testsuite/rootfs-pristine/test-modprobe/show-exports/correct.txt
new file mode 100644
index 0000000..0d659ef
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/show-exports/correct.txt
@@ -0,0 +1 @@
+0x[0-9a-fA-F]+ printA
diff --git a/testsuite/rootfs-pristine/test-modprobe/softdep-loop/etc/modprobe.d/dumb-softdep.conf b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/etc/modprobe.d/dumb-softdep.conf
new file mode 100644
index 0000000..af30b49
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/etc/modprobe.d/dumb-softdep.conf
@@ -0,0 +1 @@
+softdep mod-loop-b post: mod-loop-a
diff --git a/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.alias b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.alias.bin b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.builtin.bin b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.builtin.bin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.builtin.bin
diff --git a/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.dep b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.dep
new file mode 100644
index 0000000..869e6ea
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.dep
@@ -0,0 +1,2 @@
+kernel/mod-loop-b.ko:
+kernel/mod-loop-a.ko: kernel/mod-loop-b.ko
diff --git a/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.dep.bin b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.dep.bin
new file mode 100644
index 0000000..3d1b357
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.devname b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.devname
new file mode 100644
index 0000000..58f6d6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.devname
@@ -0,0 +1 @@
+# Device nodes to trigger on-demand module loading.
diff --git a/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.softdep b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.symbols b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.symbols
new file mode 100644
index 0000000..6c53580
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.symbols
@@ -0,0 +1,3 @@
+# Aliases for symbols, used by symbol_request().
+alias symbol:printB mod_loop_b
+alias symbol:printA mod_loop_a
diff --git a/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.symbols.bin b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.symbols.bin
new file mode 100644
index 0000000..7cb72ca
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-modprobe/softdep-loop/lib/modules/4.4.4/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-new-module/from_alias/correct.txt b/testsuite/rootfs-pristine/test-new-module/from_alias/correct.txt
new file mode 100644
index 0000000..6ed98ea
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-new-module/from_alias/correct.txt
@@ -0,0 +1,2 @@
+modname: ext4
+
diff --git a/testsuite/rootfs-pristine/test-new-module/from_alias/etc/modprobe.d/modprobe.conf b/testsuite/rootfs-pristine/test-new-module/from_alias/etc/modprobe.d/modprobe.conf
new file mode 100644
index 0000000..f9629a0
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-new-module/from_alias/etc/modprobe.d/modprobe.conf
@@ -0,0 +1 @@
+alias ext4.* ext4
diff --git a/testsuite/rootfs-pristine/test-new-module/from_name/correct.txt b/testsuite/rootfs-pristine/test-new-module/from_name/correct.txt
new file mode 100644
index 0000000..a75cd3b
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-new-module/from_name/correct.txt
@@ -0,0 +1,6 @@
+modname: ext4
+modname: balbalbalbbalbalbalbalbalbalbal
+modname: snd_hda_intel
+modname: snd_timer
+modname: iTCO_wdt
+
diff --git a/testsuite/rootfs-pristine/test-rootfs/lib/modules/a b/testsuite/rootfs-pristine/test-rootfs/lib/modules/a
new file mode 100644
index 0000000..837c960
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-rootfs/lib/modules/a
@@ -0,0 +1 @@
+kmod-test-chroot-works
diff --git a/testsuite/rootfs-pristine/test-rootfs/testdir/.gitignore b/testsuite/rootfs-pristine/test-rootfs/testdir/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-rootfs/testdir/.gitignore
diff --git a/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.alias b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.alias.bin b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.builtin b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.builtin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.builtin
diff --git a/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.builtin.bin b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.builtin.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.builtin.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.dep b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.dep
new file mode 100644
index 0000000..5476653
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.dep
@@ -0,0 +1 @@
+kernel/mod-simple.ko:
diff --git a/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.dep.bin b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.dep.bin
new file mode 100644
index 0000000..b09a854
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.devname b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.devname
new file mode 100644
index 0000000..58f6d6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.devname
@@ -0,0 +1 @@
+# Device nodes to trigger on-demand module loading.
diff --git a/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.order b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.order
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.order
diff --git a/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.softdep b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.symbols b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.symbols
new file mode 100644
index 0000000..618c345
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.symbols
@@ -0,0 +1 @@
+# Aliases for symbols, used by symbol_request().
diff --git a/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.symbols.bin b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.symbols.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/insert/lib/modules/4.4.4/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.alias b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.alias
new file mode 100644
index 0000000..ba76e18
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.alias
@@ -0,0 +1 @@
+# Aliases extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.alias.bin b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.alias.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.alias.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.builtin b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.builtin
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.builtin
diff --git a/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.builtin.bin b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.builtin.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.builtin.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.dep b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.dep
new file mode 100644
index 0000000..5476653
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.dep
@@ -0,0 +1 @@
+kernel/mod-simple.ko:
diff --git a/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.dep.bin b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.dep.bin
new file mode 100644
index 0000000..b09a854
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.dep.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.devname b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.devname
new file mode 100644
index 0000000..58f6d6d
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.devname
@@ -0,0 +1 @@
+# Device nodes to trigger on-demand module loading.
diff --git a/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.order b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.order
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.order
diff --git a/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.softdep b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.softdep
new file mode 100644
index 0000000..5554ccc
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.softdep
@@ -0,0 +1 @@
+# Soft dependencies extracted from modules themselves.
diff --git a/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.symbols b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.symbols
new file mode 100644
index 0000000..618c345
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.symbols
@@ -0,0 +1 @@
+# Aliases for symbols, used by symbol_request().
diff --git a/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.symbols.bin b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.symbols.bin
new file mode 100644
index 0000000..7075435
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/remove/lib/modules/4.4.4/modules.symbols.bin
Binary files differ
diff --git a/testsuite/rootfs-pristine/test-tools/remove/sys/module/mod_simple/holders/.gitignore b/testsuite/rootfs-pristine/test-tools/remove/sys/module/mod_simple/holders/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/remove/sys/module/mod_simple/holders/.gitignore
diff --git a/testsuite/rootfs-pristine/test-tools/remove/sys/module/mod_simple/initstate b/testsuite/rootfs-pristine/test-tools/remove/sys/module/mod_simple/initstate
new file mode 100644
index 0000000..e23fe64
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/remove/sys/module/mod_simple/initstate
@@ -0,0 +1 @@
+live
diff --git a/testsuite/rootfs-pristine/test-tools/remove/sys/module/mod_simple/refcnt b/testsuite/rootfs-pristine/test-tools/remove/sys/module/mod_simple/refcnt
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-tools/remove/sys/module/mod_simple/refcnt
@@ -0,0 +1 @@
+0
diff --git a/testsuite/rootfs-pristine/test-util/alias-correct.txt b/testsuite/rootfs-pristine/test-util/alias-correct.txt
new file mode 100644
index 0000000..86d0304
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-util/alias-correct.txt
@@ -0,0 +1,25 @@
+input test1234
+return 0
+len 8
+output test1234
+
+input test[abcfoobar]2211
+return 0
+len 19
+output test[abcfoobar]2211
+
+input bar[aaa][bbbb]sss
+return 0
+len 17
+output bar[aaa][bbbb]sss
+
+input kmod[p.b]lib
+return 0
+len 12
+output kmod[p.b]lib
+
+input [az]1234[AZ]
+return 0
+len 12
+output [az]1234[AZ]
+
diff --git a/testsuite/rootfs-pristine/test-util/freadline_wrapped-correct.txt b/testsuite/rootfs-pristine/test-util/freadline_wrapped-correct.txt
new file mode 100644
index 0000000..80c671b
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-util/freadline_wrapped-correct.txt
@@ -0,0 +1,10 @@
+this is the first line wrapped by one \
+2
+this is a single line
+1
+three line lines in a row
+3
+this line has exactly 256 chars to make fun with the implementation, so it must have word after word after word after word after word after word after word after word after word after word after word after word after word after word until it hits 256 chars
+1
+this line is very large because it has word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word until it hits 2015 chars
+1
diff --git a/testsuite/rootfs-pristine/test-util/freadline_wrapped-input.txt b/testsuite/rootfs-pristine/test-util/freadline_wrapped-input.txt
new file mode 100644
index 0000000..1c81f91
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-util/freadline_wrapped-input.txt
@@ -0,0 +1,8 @@
+this is the first line \
+wrapped by one \\
+this is a single line
+three line \
+lines \
+in a row
+this line has exactly 256 chars to make fun with the implementation, so it must have word after word after word after word after word after word after word after word after word after word after word after word after word after word until it hits 256 chars
+this line is very large because it has word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word after word until it hits 2015 chars
diff --git a/testsuite/rootfs-pristine/test-util2/write-str-safe-correct.txt b/testsuite/rootfs-pristine/test-util2/write-str-safe-correct.txt
new file mode 100644
index 0000000..30d74d2
--- /dev/null
+++ b/testsuite/rootfs-pristine/test-util2/write-str-safe-correct.txt
@@ -0,0 +1 @@
+test \ No newline at end of file
diff --git a/testsuite/setup-rootfs.sh b/testsuite/setup-rootfs.sh
new file mode 100755
index 0000000..a780f93
--- /dev/null
+++ b/testsuite/setup-rootfs.sh
@@ -0,0 +1,181 @@
+#!/bin/bash
+
+set -e
+
+ROOTFS_PRISTINE=$1
+ROOTFS=$2
+MODULE_PLAYGROUND=$3
+CONFIG_H=$4
+SYSCONFDIR=$5
+
+# create rootfs from rootfs-pristine
+
+create_rootfs() {
+ rm -rf "$ROOTFS"
+ mkdir -p $(dirname "$ROOTFS")
+ cp -r "$ROOTFS_PRISTINE" "$ROOTFS"
+ find "$ROOTFS" -type d -exec chmod +w {} \;
+ find "$ROOTFS" -type f -name .gitignore -exec rm -f {} \;
+ if [ "$MODULE_DIRECTORY" != "/lib/modules" ] ; then
+ sed -i -e "s|/lib/modules|$MODULE_DIRECTORY|g" $(find "$ROOTFS" -name \*.txt -o -name \*.conf -o -name \*.dep)
+ sed -i -e "s|$MODULE_DIRECTORY/external|/lib/modules/external|g" $(find "$ROOTFS" -name \*.txt -o -name \*.conf -o -name \*.dep)
+ for i in "$ROOTFS"/*/lib/modules/* "$ROOTFS"/*/*/lib/modules/* ; do
+ version="$(basename $i)"
+ [ $version != 'external' ] || continue
+ mod="$(dirname $i)"
+ lib="$(dirname $mod)"
+ up="$(dirname $lib)$MODULE_DIRECTORY"
+ mkdir -p "$up"
+ mv "$i" "$up"
+ done
+ fi
+
+ if [ "$SYSCONFDIR" != "/etc" ]; then
+ find "$ROOTFS" -type d -name etc -printf "%h\n" | while read -r e; do
+ mkdir -p "$(dirname $e/$SYSCONFDIR)"
+ mv $e/{etc,$SYSCONFDIR}
+ done
+ fi
+}
+
+feature_enabled() {
+ local feature=$1
+ grep KMOD_FEATURES $CONFIG_H | head -n 1 | grep -q \+$feature
+}
+
+declare -A map
+map=(
+ ["test-depmod/search-order-simple$MODULE_DIRECTORY/4.4.4/kernel/crypto/"]="mod-simple.ko"
+ ["test-depmod/search-order-simple$MODULE_DIRECTORY/4.4.4/updates/"]="mod-simple.ko"
+ ["test-depmod/search-order-same-prefix$MODULE_DIRECTORY/4.4.4/foo/"]="mod-simple.ko"
+ ["test-depmod/search-order-same-prefix$MODULE_DIRECTORY/4.4.4/foobar/"]="mod-simple.ko"
+ ["test-depmod/detect-loop$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-a.ko"]="mod-loop-a.ko"
+ ["test-depmod/detect-loop$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-b.ko"]="mod-loop-b.ko"
+ ["test-depmod/detect-loop$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-c.ko"]="mod-loop-c.ko"
+ ["test-depmod/detect-loop$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-d.ko"]="mod-loop-d.ko"
+ ["test-depmod/detect-loop$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-e.ko"]="mod-loop-e.ko"
+ ["test-depmod/detect-loop$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-f.ko"]="mod-loop-f.ko"
+ ["test-depmod/detect-loop$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-g.ko"]="mod-loop-g.ko"
+ ["test-depmod/detect-loop$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-h.ko"]="mod-loop-h.ko"
+ ["test-depmod/detect-loop$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-i.ko"]="mod-loop-i.ko"
+ ["test-depmod/detect-loop$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-j.ko"]="mod-loop-j.ko"
+ ["test-depmod/detect-loop$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-k.ko"]="mod-loop-k.ko"
+ ["test-depmod/search-order-external-first$MODULE_DIRECTORY/4.4.4/foo/"]="mod-simple.ko"
+ ["test-depmod/search-order-external-first$MODULE_DIRECTORY/4.4.4/foobar/"]="mod-simple.ko"
+ ["test-depmod/search-order-external-first/lib/modules/external/"]="mod-simple.ko"
+ ["test-depmod/search-order-external-last$MODULE_DIRECTORY/4.4.4/foo/"]="mod-simple.ko"
+ ["test-depmod/search-order-external-last$MODULE_DIRECTORY/4.4.4/foobar/"]="mod-simple.ko"
+ ["test-depmod/search-order-external-last/lib/modules/external/"]="mod-simple.ko"
+ ["test-depmod/search-order-override$MODULE_DIRECTORY/4.4.4/foo/"]="mod-simple.ko"
+ ["test-depmod/search-order-override$MODULE_DIRECTORY/4.4.4/override/"]="mod-simple.ko"
+ ["test-dependencies$MODULE_DIRECTORY/4.0.20-kmod/kernel/fs/foo/"]="mod-foo-b.ko"
+ ["test-dependencies$MODULE_DIRECTORY/4.0.20-kmod/kernel/"]="mod-foo-c.ko"
+ ["test-dependencies$MODULE_DIRECTORY/4.0.20-kmod/kernel/lib/"]="mod-foo-a.ko"
+ ["test-dependencies$MODULE_DIRECTORY/4.0.20-kmod/kernel/fs/"]="mod-foo.ko"
+ ["test-init/"]="mod-simple.ko"
+ ["test-remove/"]="mod-simple.ko"
+ ["test-modprobe/show-depends$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-a.ko"]="mod-loop-a.ko"
+ ["test-modprobe/show-depends$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-b.ko"]="mod-loop-b.ko"
+ ["test-modprobe/show-depends$MODULE_DIRECTORY/4.4.4/kernel/mod-simple.ko"]="mod-simple.ko"
+ ["test-modprobe/show-exports/mod-loop-a.ko"]="mod-loop-a.ko"
+ ["test-modprobe/softdep-loop$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-a.ko"]="mod-loop-a.ko"
+ ["test-modprobe/softdep-loop$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-b.ko"]="mod-loop-b.ko"
+ ["test-modprobe/install-cmd-loop$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-a.ko"]="mod-loop-a.ko"
+ ["test-modprobe/install-cmd-loop$MODULE_DIRECTORY/4.4.4/kernel/mod-loop-b.ko"]="mod-loop-b.ko"
+ ["test-modprobe/force$MODULE_DIRECTORY/4.4.4/kernel/"]="mod-simple.ko"
+ ["test-modprobe/oldkernel$MODULE_DIRECTORY/3.3.3/kernel/"]="mod-simple.ko"
+ ["test-modprobe/oldkernel-force$MODULE_DIRECTORY/3.3.3/kernel/"]="mod-simple.ko"
+ ["test-modprobe/alias-to-none$MODULE_DIRECTORY/4.4.4/kernel/"]="mod-simple.ko"
+ ["test-modprobe/module-param-kcmdline$MODULE_DIRECTORY/4.4.4/kernel/"]="mod-simple.ko"
+ ["test-modprobe/external/lib/modules/external/"]="mod-simple.ko"
+ ["test-modprobe/module-from-abspath/home/foo/"]="mod-simple.ko"
+ ["test-modprobe/module-from-relpath/home/foo/"]="mod-simple.ko"
+ ["test-depmod/modules-order-compressed$MODULE_DIRECTORY/4.4.4/kernel/drivers/block/cciss.ko"]="mod-fake-cciss.ko"
+ ["test-depmod/modules-order-compressed$MODULE_DIRECTORY/4.4.4/kernel/drivers/scsi/hpsa.ko"]="mod-fake-hpsa.ko"
+ ["test-depmod/modules-order-compressed$MODULE_DIRECTORY/4.4.4/kernel/drivers/scsi/scsi_mod.ko"]="mod-fake-scsi-mod.ko"
+ ["test-depmod/modules-outdir$MODULE_DIRECTORY/4.4.4/kernel/drivers/block/cciss.ko"]="mod-fake-cciss.ko"
+ ["test-depmod/modules-outdir$MODULE_DIRECTORY/4.4.4/kernel/drivers/scsi/hpsa.ko"]="mod-fake-hpsa.ko"
+ ["test-depmod/modules-outdir$MODULE_DIRECTORY/4.4.4/kernel/drivers/scsi/scsi_mod.ko"]="mod-fake-scsi-mod.ko"
+ ["test-modinfo/mod-simple-i386.ko"]="mod-simple-i386.ko"
+ ["test-modinfo/mod-simple-x86_64.ko"]="mod-simple-x86_64.ko"
+ ["test-modinfo/mod-simple-sparc64.ko"]="mod-simple-sparc64.ko"
+ ["test-modinfo/mod-simple-sha1.ko"]="mod-simple.ko"
+ ["test-modinfo/mod-simple-sha256.ko"]="mod-simple.ko"
+ ["test-modinfo/mod-simple-pkcs7.ko"]="mod-simple.ko"
+ ["test-modinfo/external/lib/modules/external/mod-simple.ko"]="mod-simple.ko"
+ ["test-tools/insert$MODULE_DIRECTORY/4.4.4/kernel/"]="mod-simple.ko"
+ ["test-tools/remove$MODULE_DIRECTORY/4.4.4/kernel/"]="mod-simple.ko"
+)
+
+gzip_array=(
+ "test-depmod/modules-order-compressed$MODULE_DIRECTORY/4.4.4/kernel/drivers/block/cciss.ko"
+ )
+
+xz_array=(
+ "test-depmod/modules-order-compressed$MODULE_DIRECTORY/4.4.4/kernel/drivers/scsi/scsi_mod.ko"
+ )
+
+zstd_array=(
+ "test-depmod/modules-order-compressed$MODULE_DIRECTORY/4.4.4/kernel/drivers/scsi/hpsa.ko"
+ )
+
+attach_sha256_array=(
+ "test-modinfo/mod-simple-sha256.ko"
+ )
+
+attach_sha1_array=(
+ "test-modinfo/mod-simple-sha1.ko"
+ )
+
+attach_pkcs7_array=(
+ "test-modinfo/mod-simple-pkcs7.ko"
+ )
+
+create_rootfs
+
+for k in "${!map[@]}"; do
+ dst=${ROOTFS}/$k
+ src=${MODULE_PLAYGROUND}/${map[$k]}
+
+ if [[ $dst = */ ]]; then
+ install -d "$dst"
+ install -t "$dst" "$src"
+ else
+ install -D "$src" "$dst"
+ fi
+done
+
+# start poking the final rootfs...
+
+# compress modules with each format if feature is enabled
+if feature_enabled ZLIB; then
+ for m in "${gzip_array[@]}"; do
+ gzip "$ROOTFS/$m"
+ done
+fi
+
+if feature_enabled XZ; then
+ for m in "${xz_array[@]}"; do
+ xz "$ROOTFS/$m"
+ done
+fi
+
+if feature_enabled ZSTD; then
+ for m in "${zstd_array[@]}"; do
+ zstd --rm $ROOTFS/$m
+ done
+fi
+
+for m in "${attach_sha1_array[@]}"; do
+ cat "${MODULE_PLAYGROUND}/dummy.sha1" >>"${ROOTFS}/$m"
+done
+
+for m in "${attach_sha256_array[@]}"; do
+ cat "${MODULE_PLAYGROUND}/dummy.sha256" >>"${ROOTFS}/$m"
+done
+
+for m in "${attach_pkcs7_array[@]}"; do
+ cat "${MODULE_PLAYGROUND}/dummy.pkcs7" >>"${ROOTFS}/$m"
+done
+
+touch testsuite/stamp-rootfs
diff --git a/testsuite/stripped-module.h b/testsuite/stripped-module.h
new file mode 100644
index 0000000..83986b2
--- /dev/null
+++ b/testsuite/stripped-module.h
@@ -0,0 +1,29 @@
+#pragma once
+
+enum module_state
+{
+ MODULE_STATE_LIVE,
+ MODULE_STATE_COMING,
+ MODULE_STATE_GOING,
+};
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define MODULE_NAME_LEN (64 - sizeof(unsigned long))
+
+struct module
+{
+ enum module_state state;
+
+ /* Member of list of modules */
+ struct list_head list;
+
+ /* Unique handle for this module */
+ char name[MODULE_NAME_LEN];
+};
+
+/* padding */
+#define MODULE_NAME_OFFSET_64 4 + 4 + 2 * 8
+#define MODULE_NAME_OFFSET_32 4 + 2 * 4
diff --git a/testsuite/test-array.c b/testsuite/test-array.c
new file mode 100644
index 0000000..ef1e1e9
--- /dev/null
+++ b/testsuite/test-array.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <shared/array.h>
+
+#include "testsuite.h"
+
+static int test_array_append1(const struct test *t)
+{
+ struct array array;
+ const char *c1 = "test1";
+
+ array_init(&array, 2);
+ array_append(&array, c1);
+ assert_return(array.count == 1, EXIT_FAILURE);
+ assert_return(array.array[0] == c1, EXIT_FAILURE);
+ array_free_array(&array);
+
+ return 0;
+}
+DEFINE_TEST(test_array_append1,
+ .description = "test simple array append");
+
+
+static int test_array_append2(const struct test *t)
+{
+ struct array array;
+ const char *c1 = "test1";
+ const char *c2 = "test2";
+ const char *c3 = "test3";
+
+ array_init(&array, 2);
+ array_append(&array, c1);
+ array_append(&array, c2);
+ array_append(&array, c3);
+ assert_return(array.count == 3, EXIT_FAILURE);
+ assert_return(array.array[0] == c1, EXIT_FAILURE);
+ assert_return(array.array[1] == c2, EXIT_FAILURE);
+ assert_return(array.array[2] == c3, EXIT_FAILURE);
+ array_free_array(&array);
+
+ return 0;
+}
+DEFINE_TEST(test_array_append2,
+ .description = "test array append over step");
+
+static int test_array_append_unique(const struct test *t)
+{
+ struct array array;
+ const char *c1 = "test1";
+ const char *c2 = "test2";
+ const char *c3 = "test3";
+
+ array_init(&array, 2);
+ array_append_unique(&array, c1);
+ array_append_unique(&array, c2);
+ array_append_unique(&array, c3);
+ array_append_unique(&array, c3);
+ array_append_unique(&array, c2);
+ array_append_unique(&array, c1);
+ assert_return(array.count == 3, EXIT_FAILURE);
+ assert_return(array.array[0] == c1, EXIT_FAILURE);
+ assert_return(array.array[1] == c2, EXIT_FAILURE);
+ assert_return(array.array[2] == c3, EXIT_FAILURE);
+ array_free_array(&array);
+
+ return 0;
+}
+DEFINE_TEST(test_array_append_unique,
+ .description = "test array append unique");
+
+static int strptrcmp(const void *pa, const void *pb) {
+ const char *a = *(const char **)pa;
+ const char *b = *(const char **)pb;
+
+ return strcmp(a, b);
+}
+
+static int test_array_sort(const struct test *t)
+{
+ struct array array;
+ const char *c1 = "test1";
+ const char *c2 = "test2";
+ const char *c3 = "test3";
+
+ array_init(&array, 2);
+ array_append(&array, c1);
+ array_append(&array, c2);
+ array_append(&array, c3);
+ array_append(&array, c2);
+ array_append(&array, c3);
+ array_append(&array, c1);
+ array_sort(&array, strptrcmp);
+ assert_return(array.count == 6, EXIT_FAILURE);
+ assert_return(array.array[0] == c1, EXIT_FAILURE);
+ assert_return(array.array[1] == c1, EXIT_FAILURE);
+ assert_return(array.array[2] == c2, EXIT_FAILURE);
+ assert_return(array.array[3] == c2, EXIT_FAILURE);
+ assert_return(array.array[4] == c3, EXIT_FAILURE);
+ assert_return(array.array[5] == c3, EXIT_FAILURE);
+ array_free_array(&array);
+
+ return 0;
+}
+DEFINE_TEST(test_array_sort,
+ .description = "test array sort");
+
+static int test_array_remove_at(const struct test *t)
+{
+ struct array array;
+ const char *c1 = "test1";
+ const char *c2 = "test2";
+ const char *c3 = "test3";
+
+ array_init(&array, 2);
+ array_append(&array, c1);
+ array_append(&array, c2);
+ array_append(&array, c3);
+
+ array_remove_at(&array, 2);
+ assert_return(array.count == 2, EXIT_FAILURE);
+ assert_return(array.array[0] == c1, EXIT_FAILURE);
+ assert_return(array.array[1] == c2, EXIT_FAILURE);
+
+ array_remove_at(&array, 0);
+ assert_return(array.count == 1, EXIT_FAILURE);
+ assert_return(array.array[0] == c2, EXIT_FAILURE);
+
+ array_remove_at(&array, 0);
+ assert_return(array.count == 0, EXIT_FAILURE);
+
+ array_append(&array, c1);
+ array_append(&array, c2);
+ array_append(&array, c3);
+
+ array_remove_at(&array, 1);
+ assert_return(array.count == 2, EXIT_FAILURE);
+ assert_return(array.array[0] == c1, EXIT_FAILURE);
+ assert_return(array.array[1] == c3, EXIT_FAILURE);
+
+ array_free_array(&array);
+
+ return 0;
+}
+DEFINE_TEST(test_array_remove_at,
+ .description = "test array remove at");
+
+static int test_array_pop(const struct test *t)
+{
+ struct array array;
+ const char *c1 = "test1";
+ const char *c2 = "test2";
+ const char *c3 = "test3";
+
+ array_init(&array, 2);
+ array_append(&array, c1);
+ array_append(&array, c2);
+ array_append(&array, c3);
+
+
+ array_pop(&array);
+
+ assert_return(array.count == 2, EXIT_FAILURE);
+ assert_return(array.array[0] == c1, EXIT_FAILURE);
+ assert_return(array.array[1] == c2, EXIT_FAILURE);
+
+ array_pop(&array);
+ array_pop(&array);
+
+ assert_return(array.count == 0, EXIT_FAILURE);
+
+ array_free_array(&array);
+
+ return 0;
+}
+
+DEFINE_TEST(test_array_pop,
+ .description = "test array pop");
+
+TESTSUITE_MAIN();
diff --git a/testsuite/test-blacklist.c b/testsuite/test-blacklist.c
new file mode 100644
index 0000000..969567d
--- /dev/null
+++ b/testsuite/test-blacklist.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2011-2013 ProFUSION embedded systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <shared/util.h>
+
+#include <libkmod/libkmod.h>
+
+/* good luck bulding a kmod_list outside of the library... makes this blacklist
+ * function rather pointless */
+#include <libkmod/libkmod-internal.h>
+
+/* FIXME: hack, change name so we don't clash */
+#undef ERR
+#include "testsuite.h"
+
+static int blacklist_1(const struct test *t)
+{
+ struct kmod_ctx *ctx;
+ struct kmod_list *list = NULL, *l, *filtered;
+ struct kmod_module *mod;
+ int err;
+ size_t len = 0;
+
+ const char *names[] = { "pcspkr", "pcspkr2", "floppy", "ext4", NULL };
+ const char **name;
+
+ ctx = kmod_new(NULL, NULL);
+ if (ctx == NULL)
+ exit(EXIT_FAILURE);
+
+ for(name = names; *name; name++) {
+ err = kmod_module_new_from_name(ctx, *name, &mod);
+ if (err < 0)
+ goto fail_lookup;
+ list = kmod_list_append(list, mod);
+ }
+
+ err = kmod_module_apply_filter(ctx, KMOD_FILTER_BLACKLIST, list,
+ &filtered);
+ if (err < 0) {
+ ERR("Could not filter: %s\n", strerror(-err));
+ goto fail;
+ }
+ if (filtered == NULL) {
+ ERR("All modules were filtered out!\n");
+ goto fail;
+ }
+
+ kmod_list_foreach(l, filtered) {
+ const char *modname;
+ mod = kmod_module_get_module(l);
+ modname = kmod_module_get_name(mod);
+ if (streq("pcspkr", modname) || streq("floppy", modname))
+ goto fail;
+ len++;
+ kmod_module_unref(mod);
+ }
+
+ if (len != 2)
+ goto fail;
+
+ kmod_module_unref_list(filtered);
+ kmod_module_unref_list(list);
+ kmod_unref(ctx);
+
+ return EXIT_SUCCESS;
+
+fail:
+ kmod_module_unref_list(list);
+fail_lookup:
+ kmod_unref(ctx);
+ return EXIT_FAILURE;
+}
+
+DEFINE_TEST(blacklist_1,
+ .description = "check if modules are correctly blacklisted",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-blacklist/",
+ },
+ .need_spawn = true,
+);
+
+TESTSUITE_MAIN();
diff --git a/testsuite/test-dependencies.c b/testsuite/test-dependencies.c
new file mode 100644
index 0000000..38f5fc1
--- /dev/null
+++ b/testsuite/test-dependencies.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2011-2013 ProFUSION embedded systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <shared/util.h>
+
+#include <libkmod/libkmod.h>
+
+#include "testsuite.h"
+
+#define TEST_UNAME "4.0.20-kmod"
+
+static noreturn int test_dependencies(const struct test *t)
+{
+ struct kmod_ctx *ctx;
+ struct kmod_module *mod = NULL;
+ struct kmod_list *list, *l;
+ int err;
+ size_t len = 0;
+ int fooa = 0, foob = 0, fooc = 0;
+
+ ctx = kmod_new(NULL, NULL);
+ if (ctx == NULL)
+ exit(EXIT_FAILURE);
+
+ err = kmod_module_new_from_name(ctx, "mod-foo", &mod);
+ if (err < 0 || mod == NULL) {
+ kmod_unref(ctx);
+ exit(EXIT_FAILURE);
+ }
+
+ list = kmod_module_get_dependencies(mod);
+
+ kmod_list_foreach(l, list) {
+ struct kmod_module *m = kmod_module_get_module(l);
+ const char *name = kmod_module_get_name(m);
+
+ if (streq(name, "mod_foo_a"))
+ fooa = 1;
+ if (streq(name, "mod_foo_b"))
+ foob = 1;
+ else if (streq(name, "mod_foo_c"))
+ fooc = 1;
+
+ fprintf(stderr, "name=%s", name);
+ kmod_module_unref(m);
+ len++;
+ }
+
+ /* fooa, foob, fooc */
+ if (len != 3 || !fooa || !foob || !fooc)
+ exit(EXIT_FAILURE);
+
+ kmod_module_unref_list(list);
+ kmod_module_unref(mod);
+ kmod_unref(ctx);
+
+ exit(EXIT_SUCCESS);
+}
+DEFINE_TEST(test_dependencies,
+ .description = "test if kmod_module_get_dependencies works",
+ .config = {
+ [TC_UNAME_R] = TEST_UNAME,
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-dependencies/",
+ },
+ .need_spawn = true);
+
+TESTSUITE_MAIN();
diff --git a/testsuite/test-depmod.c b/testsuite/test-depmod.c
new file mode 100644
index 0000000..c96dbf0
--- /dev/null
+++ b/testsuite/test-depmod.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2012-2013 ProFUSION embedded systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "testsuite.h"
+
+#define MODULES_UNAME "4.4.4"
+#define MODULES_ORDER_ROOTFS TESTSUITE_ROOTFS "test-depmod/modules-order-compressed"
+#define MODULES_ORDER_LIB_MODULES MODULES_ORDER_ROOTFS MODULE_DIRECTORY "/" MODULES_UNAME
+static noreturn int depmod_modules_order_for_compressed(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/depmod";
+ const char *const args[] = {
+ progname,
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+
+DEFINE_TEST(depmod_modules_order_for_compressed,
+ .description = "check if depmod let aliases in right order when using compressed modules",
+ .config = {
+ [TC_UNAME_R] = MODULES_UNAME,
+ [TC_ROOTFS] = MODULES_ORDER_ROOTFS,
+ },
+ .output = {
+ .files = (const struct keyval[]) {
+ { MODULES_ORDER_LIB_MODULES "/correct-modules.alias",
+ MODULES_ORDER_LIB_MODULES "/modules.alias" },
+ { }
+ },
+ });
+
+#define MODULES_OUTDIR_ROOTFS TESTSUITE_ROOTFS "test-depmod/modules-outdir"
+#define MODULES_OUTDIR_LIB_MODULES_OUTPUT MODULES_OUTDIR_ROOTFS "/outdir" MODULE_DIRECTORY "/" MODULES_UNAME
+#define MODULES_OUTDIR_LIB_MODULES_INPUT MODULES_OUTDIR_ROOTFS MODULE_DIRECTORY "/" MODULES_UNAME
+static noreturn int depmod_modules_outdir(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/depmod";
+ const char *const args[] = {
+ progname,
+ "--outdir", MODULES_OUTDIR_ROOTFS "/outdir/",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+
+DEFINE_TEST(depmod_modules_outdir,
+ .description = "check if depmod honours the outdir option",
+ .config = {
+ [TC_UNAME_R] = MODULES_UNAME,
+ [TC_ROOTFS] = MODULES_OUTDIR_ROOTFS,
+ },
+ .output = {
+ .files = (const struct keyval[]) {
+ { MODULES_OUTDIR_LIB_MODULES_OUTPUT "/modules.dep",
+ MODULES_OUTDIR_ROOTFS "/correct-modules.dep" },
+ { MODULES_OUTDIR_LIB_MODULES_OUTPUT "/modules.alias",
+ MODULES_OUTDIR_ROOTFS "/correct-modules.alias" },
+ { }
+ },
+ });
+
+#define SEARCH_ORDER_SIMPLE_ROOTFS TESTSUITE_ROOTFS "test-depmod/search-order-simple"
+#define SEARCH_ORDER_SIMPLE_LIB_MODULES SEARCH_ORDER_SIMPLE_ROOTFS MODULE_DIRECTORY "/" MODULES_UNAME
+static noreturn int depmod_search_order_simple(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/depmod";
+ const char *const args[] = {
+ progname,
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(depmod_search_order_simple,
+ .description = "check if depmod honor search order in config",
+ .config = {
+ [TC_UNAME_R] = MODULES_UNAME,
+ [TC_ROOTFS] = SEARCH_ORDER_SIMPLE_ROOTFS,
+ },
+ .output = {
+ .files = (const struct keyval[]) {
+ { SEARCH_ORDER_SIMPLE_LIB_MODULES "/correct-modules.dep",
+ SEARCH_ORDER_SIMPLE_LIB_MODULES "/modules.dep" },
+ { }
+ },
+ });
+
+#define SEARCH_ORDER_SAME_PREFIX_ROOTFS TESTSUITE_ROOTFS "test-depmod/search-order-same-prefix"
+#define SEARCH_ORDER_SAME_PREFIX_LIB_MODULES SEARCH_ORDER_SAME_PREFIX_ROOTFS MODULE_DIRECTORY "/" MODULES_UNAME
+static noreturn int depmod_search_order_same_prefix(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/depmod";
+ const char *const args[] = {
+ progname,
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(depmod_search_order_same_prefix,
+ .description = "check if depmod honor search order in config with same prefix",
+ .config = {
+ [TC_UNAME_R] = MODULES_UNAME,
+ [TC_ROOTFS] = SEARCH_ORDER_SAME_PREFIX_ROOTFS,
+ },
+ .output = {
+ .files = (const struct keyval[]) {
+ { SEARCH_ORDER_SAME_PREFIX_LIB_MODULES "/correct-modules.dep",
+ SEARCH_ORDER_SAME_PREFIX_LIB_MODULES "/modules.dep" },
+ { }
+ },
+ });
+
+#define DETECT_LOOP_ROOTFS TESTSUITE_ROOTFS "test-depmod/detect-loop"
+static noreturn int depmod_detect_loop(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/depmod";
+ const char *const args[] = {
+ progname,
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(depmod_detect_loop,
+ .description = "check if depmod detects module loops correctly",
+ .config = {
+ [TC_UNAME_R] = MODULES_UNAME,
+ [TC_ROOTFS] = DETECT_LOOP_ROOTFS,
+ },
+ .expected_fail = true,
+ .output = {
+ .err = DETECT_LOOP_ROOTFS "/correct.txt",
+ });
+
+#define SEARCH_ORDER_EXTERNAL_FIRST_ROOTFS TESTSUITE_ROOTFS "test-depmod/search-order-external-first"
+#define SEARCH_ORDER_EXTERNAL_FIRST_LIB_MODULES SEARCH_ORDER_EXTERNAL_FIRST_ROOTFS MODULE_DIRECTORY "/" MODULES_UNAME
+static noreturn int depmod_search_order_external_first(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/depmod";
+ const char *const args[] = {
+ progname,
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(depmod_search_order_external_first,
+ .description = "check if depmod honor external keyword with higher priority",
+ .config = {
+ [TC_UNAME_R] = MODULES_UNAME,
+ [TC_ROOTFS] = SEARCH_ORDER_EXTERNAL_FIRST_ROOTFS,
+ },
+ .output = {
+ .files = (const struct keyval[]) {
+ { SEARCH_ORDER_EXTERNAL_FIRST_LIB_MODULES "/correct-modules.dep",
+ SEARCH_ORDER_EXTERNAL_FIRST_LIB_MODULES "/modules.dep" },
+ { }
+ },
+ });
+
+#define SEARCH_ORDER_EXTERNAL_LAST_ROOTFS TESTSUITE_ROOTFS "test-depmod/search-order-external-last"
+#define SEARCH_ORDER_EXTERNAL_LAST_LIB_MODULES SEARCH_ORDER_EXTERNAL_LAST_ROOTFS MODULE_DIRECTORY "/" MODULES_UNAME
+static noreturn int depmod_search_order_external_last(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/depmod";
+ const char *const args[] = {
+ progname,
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(depmod_search_order_external_last,
+ .description = "check if depmod honor external keyword with lower priority",
+ .config = {
+ [TC_UNAME_R] = MODULES_UNAME,
+ [TC_ROOTFS] = SEARCH_ORDER_EXTERNAL_LAST_ROOTFS,
+ },
+ .output = {
+ .files = (const struct keyval[]) {
+ { SEARCH_ORDER_EXTERNAL_LAST_LIB_MODULES "/correct-modules.dep",
+ SEARCH_ORDER_EXTERNAL_LAST_LIB_MODULES "/modules.dep" },
+ { }
+ },
+ });
+
+#define SEARCH_ORDER_OVERRIDE_ROOTFS TESTSUITE_ROOTFS "test-depmod/search-order-override"
+#define SEARCH_ORDER_OVERRIDE_LIB_MODULES SEARCH_ORDER_OVERRIDE_ROOTFS MODULE_DIRECTORY "/" MODULES_UNAME
+static noreturn int depmod_search_order_override(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/depmod";
+ const char *const args[] = {
+ progname,
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(depmod_search_order_override,
+ .description = "check if depmod honor override keyword",
+ .config = {
+ [TC_UNAME_R] = MODULES_UNAME,
+ [TC_ROOTFS] = SEARCH_ORDER_OVERRIDE_ROOTFS,
+ },
+ .output = {
+ .files = (const struct keyval[]) {
+ { SEARCH_ORDER_OVERRIDE_LIB_MODULES "/correct-modules.dep",
+ SEARCH_ORDER_OVERRIDE_LIB_MODULES "/modules.dep" },
+ { }
+ },
+ });
+
+TESTSUITE_MAIN();
diff --git a/testsuite/test-hash.c b/testsuite/test-hash.c
new file mode 100644
index 0000000..1bea04e
--- /dev/null
+++ b/testsuite/test-hash.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <shared/hash.h>
+#include <shared/util.h>
+
+#include "testsuite.h"
+
+static int freecount;
+
+static void countfreecalls(void *v)
+{
+ freecount++;
+}
+
+static int test_hash_new(const struct test *t)
+{
+ struct hash *h = hash_new(8, NULL);
+ assert_return(h != NULL, EXIT_FAILURE);
+ hash_free(h);
+ return 0;
+}
+DEFINE_TEST(test_hash_new,
+ .description = "test hash_new");
+
+
+static int test_hash_get_count(const struct test *t)
+{
+ struct hash *h = hash_new(8, NULL);
+ const char *k1 = "k1", *k2 = "k2", *k3 = "k3";
+ const char *v1 = "v1", *v2 = "v2", *v3 = "v3";
+
+ hash_add(h, k1, v1);
+ hash_add(h, k2, v2);
+ hash_add(h, k3, v3);
+
+ assert_return(hash_get_count(h) == 3, EXIT_FAILURE);
+
+ hash_free(h);
+ return 0;
+}
+DEFINE_TEST(test_hash_get_count,
+ .description = "test hash_add / hash_get_count");
+
+
+static int test_hash_replace(const struct test *t)
+{
+ struct hash *h = hash_new(8, countfreecalls);
+ const char *k1 = "k1", *k2 = "k2", *k3 = "k3";
+ const char *v1 = "v1", *v2 = "v2", *v3 = "v3", *v4 = "v4";
+ const char *v;
+ int r = 0;
+
+ r |= hash_add(h, k1, v1);
+ r |= hash_add(h, k2, v2);
+ r |= hash_add(h, k3, v3);
+
+ /* replace v1 */
+ r |= hash_add(h, k1, v4);
+
+ assert_return(r == 0, EXIT_FAILURE);
+ assert_return(hash_get_count(h) == 3, EXIT_FAILURE);
+
+ v = hash_find(h, "k1");
+ assert_return(streq(v, v4), EXIT_FAILURE);
+
+ assert_return(freecount == 1, EXIT_FAILURE);
+
+ hash_free(h);
+ return 0;
+}
+DEFINE_TEST(test_hash_replace,
+ .description = "test hash_add replacing existing value");
+
+
+static int test_hash_replace_failing(const struct test *t)
+{
+ struct hash *h = hash_new(8, countfreecalls);
+ const char *k1 = "k1", *k2 = "k2", *k3 = "k3";
+ const char *v1 = "v1", *v2 = "v2", *v3 = "v3", *v4 = "v4";
+ const char *v;
+ int r = 0;
+
+ r |= hash_add(h, k1, v1);
+ r |= hash_add(h, k2, v2);
+ r |= hash_add(h, k3, v3);
+
+ assert_return(r == 0, EXIT_FAILURE);
+
+ /* replace v1 */
+ r = hash_add_unique(h, k1, v4);
+ assert_return(r != 0, EXIT_FAILURE);
+ assert_return(hash_get_count(h) == 3, EXIT_FAILURE);
+
+ v = hash_find(h, "k1");
+ assert_return(streq(v, v1), EXIT_FAILURE);
+
+ assert_return(freecount == 0, EXIT_FAILURE);
+
+ hash_free(h);
+ return 0;
+}
+DEFINE_TEST(test_hash_replace_failing,
+ .description = "test hash_add_unique failing to replace existing value");
+
+
+static int test_hash_iter(const struct test *t)
+{
+ struct hash *h = hash_new(8, NULL);
+ struct hash *h2 = hash_new(8, NULL);
+ const char *k1 = "k1", *k2 = "k2", *k3 = "k3";
+ const char *v1 = "v1", *v2 = "v2", *v3 = "v3";
+ struct hash_iter iter;
+ const char *k, *v;
+
+ hash_add(h, k1, v1);
+ hash_add(h2, k1, v1);
+ hash_add(h, k2, v2);
+ hash_add(h2, k2, v2);
+ hash_add(h, k3, v3);
+ hash_add(h2, k3, v3);
+
+ for (hash_iter_init(h, &iter);
+ hash_iter_next(&iter, &k, (const void **) &v);) {
+ v2 = hash_find(h2, k);
+ assert_return(v2 != NULL, EXIT_FAILURE);
+ hash_del(h2, k);
+ }
+
+ assert_return(hash_get_count(h) == 3, EXIT_FAILURE);
+ assert_return(hash_get_count(h2) == 0, EXIT_FAILURE);
+
+ hash_free(h);
+ hash_free(h2);
+ return 0;
+}
+DEFINE_TEST(test_hash_iter,
+ .description = "test hash_iter");
+
+
+static int test_hash_iter_after_del(const struct test *t)
+{
+ struct hash *h = hash_new(8, NULL);
+ struct hash *h2 = hash_new(8, NULL);
+ const char *k1 = "k1", *k2 = "k2", *k3 = "k3";
+ const char *v1 = "v1", *v2 = "v2", *v3 = "v3";
+ struct hash_iter iter;
+ const char *k, *v;
+
+ hash_add(h, k1, v1);
+ hash_add(h2, k1, v1);
+ hash_add(h, k2, v2);
+ hash_add(h2, k2, v2);
+ hash_add(h, k3, v3);
+ hash_add(h2, k3, v3);
+
+ hash_del(h, k1);
+
+ for (hash_iter_init(h, &iter);
+ hash_iter_next(&iter, &k, (const void **) &v);) {
+ v2 = hash_find(h2, k);
+ assert_return(v2 != NULL, EXIT_FAILURE);
+ hash_del(h2, k);
+ }
+
+ assert_return(hash_get_count(h) == 2, EXIT_FAILURE);
+ assert_return(hash_get_count(h2) == 1, EXIT_FAILURE);
+
+ hash_free(h);
+ hash_free(h2);
+ return 0;
+}
+DEFINE_TEST(test_hash_iter_after_del,
+ .description = "test hash_iter, after deleting element");
+
+
+static int test_hash_free(const struct test *t)
+{
+ struct hash *h = hash_new(8, countfreecalls);
+ const char *k1 = "k1", *k2 = "k2", *k3 = "k3";
+ const char *v1 = "v1", *v2 = "v2", *v3 = "v3";
+
+ hash_add(h, k1, v1);
+ hash_add(h, k2, v2);
+ hash_add(h, k3, v3);
+
+ hash_del(h, k1);
+
+ assert_return(freecount == 1, EXIT_FAILURE);
+
+ assert_return(hash_get_count(h) == 2, EXIT_FAILURE);
+
+ hash_free(h);
+
+ assert_return(freecount == 3, EXIT_FAILURE);
+
+ return 0;
+}
+DEFINE_TEST(test_hash_free,
+ .description = "test hash_free calling free function for all values");
+
+
+static int test_hash_add_unique(const struct test *t)
+{
+ const char *k[] = { "k1", "k2", "k3", "k4", "k5" };
+ const char *v[] = { "v1", "v2", "v3", "v4", "v5" };
+ unsigned int i, j, N;
+
+ N = ARRAY_SIZE(k);
+ for (i = 0; i < N; i++) {
+ /* With N - 1 buckets, there'll be a bucket with more than one key. */
+ struct hash *h = hash_new(N - 1, NULL);
+
+ /* Add the keys in different orders. */
+ for (j = 0; j < N; j++) {
+ unsigned int idx = (j + i) % N;
+ hash_add_unique(h, k[idx], v[idx]);
+ }
+
+ assert_return(hash_get_count(h) == N, EXIT_FAILURE);
+ hash_free(h);
+ }
+ return 0;
+}
+DEFINE_TEST(test_hash_add_unique,
+ .description = "test hash_add_unique with different key orders")
+
+
+static int test_hash_massive_add_del(const struct test *t)
+{
+ char buf[1024 * 8];
+ char *k;
+ struct hash *h;
+ unsigned int i, N = 1024;
+
+ h = hash_new(8, NULL);
+
+ k = &buf[0];
+ for (i = 0; i < N; i++) {
+ snprintf(k, 8, "k%d", i);
+ hash_add(h, k, k);
+ k += 8;
+ }
+
+ assert_return(hash_get_count(h) == N, EXIT_FAILURE);
+
+ k = &buf[0];
+ for (i = 0; i < N; i++) {
+ hash_del(h, k);
+ k += 8;
+ }
+
+ assert_return(hash_get_count(h) == 0, EXIT_FAILURE);
+
+ hash_free(h);
+ return 0;
+}
+DEFINE_TEST(test_hash_massive_add_del,
+ .description = "test multiple adds followed by multiple dels")
+
+TESTSUITE_MAIN();
diff --git a/testsuite/test-init.c b/testsuite/test-init.c
new file mode 100644
index 0000000..edbfc23
--- /dev/null
+++ b/testsuite/test-init.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2012-2013 ProFUSION embedded systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <shared/macro.h>
+
+#include <libkmod/libkmod.h>
+
+#include "testsuite.h"
+
+static noreturn int test_load_resources(const struct test *t)
+{
+ struct kmod_ctx *ctx;
+ const char *null_config = NULL;
+ int err;
+
+ ctx = kmod_new(NULL, &null_config);
+ if (ctx == NULL)
+ exit(EXIT_FAILURE);
+
+ kmod_set_log_priority(ctx, 7);
+
+ err = kmod_load_resources(ctx);
+ if (err != 0) {
+ ERR("could not load libkmod resources: %s\n", strerror(-err));
+ exit(EXIT_FAILURE);
+ }
+
+ kmod_unref(ctx);
+
+ exit(EXIT_SUCCESS);
+}
+DEFINE_TEST(test_load_resources,
+ .description = "test if kmod_load_resources works (recent modprobe on kernel without modules.builtin.modinfo)",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-init-load-resources/",
+ [TC_UNAME_R] = "5.6.0",
+ },
+ .need_spawn = true);
+
+DEFINE_TEST(test_load_resources,
+ .description = "test if kmod_load_resources works with empty modules.builtin.aliases.bin (recent depmod on kernel without modules.builtin.modinfo)",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-init-load-resources-empty-builtin-aliases-bin/",
+ [TC_UNAME_R] = "5.6.0",
+ },
+ .need_spawn = true);
+
+static noreturn int test_initlib(const struct test *t)
+{
+ struct kmod_ctx *ctx;
+ const char *null_config = NULL;
+
+ ctx = kmod_new(NULL, &null_config);
+ if (ctx == NULL)
+ exit(EXIT_FAILURE);
+
+ kmod_unref(ctx);
+
+ exit(EXIT_SUCCESS);
+}
+DEFINE_TEST(test_initlib,
+ .description = "test if libkmod's init function work");
+
+static noreturn int test_insert(const struct test *t)
+{
+ struct kmod_ctx *ctx;
+ struct kmod_module *mod;
+ const char *null_config = NULL;
+ int err;
+
+ ctx = kmod_new(NULL, &null_config);
+ if (ctx == NULL)
+ exit(EXIT_FAILURE);
+
+ err = kmod_module_new_from_path(ctx, "/mod-simple.ko", &mod);
+ if (err != 0) {
+ ERR("could not create module from path: %m\n");
+ exit(EXIT_FAILURE);
+ }
+
+ err = kmod_module_insert_module(mod, 0, NULL);
+ if (err != 0) {
+ ERR("could not insert module: %m\n");
+ exit(EXIT_FAILURE);
+ }
+ kmod_unref(ctx);
+
+ exit(EXIT_SUCCESS);
+}
+DEFINE_TEST(test_insert,
+ .description = "test if libkmod's insert_module returns ok",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-init/",
+ [TC_INIT_MODULE_RETCODES] = "bla:1:20",
+ },
+ .modules_loaded = "mod_simple",
+ .need_spawn = true);
+
+static noreturn int test_remove(const struct test *t)
+{
+ struct kmod_ctx *ctx;
+ struct kmod_module *mod_simple, *mod_bla;
+ const char *null_config = NULL;
+ int err;
+
+ ctx = kmod_new(NULL, &null_config);
+ if (ctx == NULL)
+ exit(EXIT_FAILURE);
+
+ err = kmod_module_new_from_name(ctx, "mod-simple", &mod_simple);
+ if (err != 0) {
+ ERR("could not create module from name: %s\n", strerror(-err));
+ exit(EXIT_FAILURE);
+ }
+
+ err = kmod_module_new_from_name(ctx, "bla", &mod_bla);
+ if (err != 0) {
+ ERR("could not create module from name: %s\n", strerror(-err));
+ exit(EXIT_FAILURE);
+ }
+
+ err = kmod_module_remove_module(mod_simple, 0);
+ if (err != 0) {
+ ERR("could not remove module: %s\n", strerror(-err));
+ exit(EXIT_FAILURE);
+ }
+
+ err = kmod_module_remove_module(mod_bla, 0);
+ if (err != -ENOENT) {
+ ERR("wrong return code for failure test: %d\n", err);
+ exit(EXIT_FAILURE);
+ }
+
+ kmod_unref(ctx);
+
+ exit(EXIT_SUCCESS);
+}
+DEFINE_TEST(test_remove,
+ .description = "test if libkmod's remove_module returns ok",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-remove/",
+ [TC_DELETE_MODULE_RETCODES] =
+ "mod-simple:0:0:bla:-1:" STRINGIFY(ENOENT),
+ },
+ .need_spawn = true);
+
+TESTSUITE_MAIN();
diff --git a/testsuite/test-initstate.c b/testsuite/test-initstate.c
new file mode 100644
index 0000000..9332e8f
--- /dev/null
+++ b/testsuite/test-initstate.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <libkmod/libkmod.h>
+
+#include <shared/macro.h>
+
+#include "testsuite.h"
+
+
+static noreturn int test_initstate_from_lookup(const struct test *t)
+{
+ struct kmod_ctx *ctx;
+ struct kmod_list *list = NULL;
+ struct kmod_module *mod;
+ const char *null_config = NULL;
+ int err, r;
+
+ ctx = kmod_new(NULL, &null_config);
+ if (ctx == NULL)
+ exit(EXIT_FAILURE);
+
+ err = kmod_module_new_from_lookup(ctx, "fake-builtin", &list);
+ if (err < 0) {
+ ERR("could not create module from lookup: %s\n", strerror(-err));
+ exit(EXIT_FAILURE);
+ }
+
+ if (!list) {
+ ERR("could not create module from lookup: module not found: fake-builtin\n");
+ exit(EXIT_FAILURE);
+ }
+
+ mod = kmod_module_get_module(list);
+
+ r = kmod_module_get_initstate(mod);
+ if (r != KMOD_MODULE_BUILTIN) {
+ ERR("module should have builtin state but is: %s\n",
+ kmod_module_initstate_str(r));
+ exit(EXIT_FAILURE);
+ }
+
+ kmod_module_unref(mod);
+ kmod_module_unref_list(list);
+ kmod_unref(ctx);
+
+ exit(EXIT_SUCCESS);
+}
+DEFINE_TEST(test_initstate_from_lookup,
+ .description = "test if libkmod return correct initstate for builtin module from lookup",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-initstate",
+ [TC_UNAME_R] = "4.4.4",
+ },
+ .need_spawn = true);
+
+static noreturn int test_initstate_from_name(const struct test *t)
+{
+ struct kmod_ctx *ctx;
+ struct kmod_module *mod = NULL;
+ const char *null_config = NULL;
+ int err, r;
+
+ ctx = kmod_new(NULL, &null_config);
+ if (ctx == NULL)
+ exit(EXIT_FAILURE);
+
+ err = kmod_module_new_from_name(ctx, "fake-builtin", &mod);
+ if (err != 0) {
+ ERR("could not create module from lookup: %s\n", strerror(-err));
+ exit(EXIT_FAILURE);
+ }
+
+ if (!mod) {
+ ERR("could not create module from lookup: module not found: fake-builtin\n");
+ exit(EXIT_FAILURE);
+ }
+
+ r = kmod_module_get_initstate(mod);
+ if (r != KMOD_MODULE_BUILTIN) {
+ ERR("module should have builtin state but is: %s\n",
+ kmod_module_initstate_str(r));
+ exit(EXIT_FAILURE);
+ }
+
+ kmod_module_unref(mod);
+ kmod_unref(ctx);
+
+ exit(EXIT_SUCCESS);
+}
+DEFINE_TEST(test_initstate_from_name,
+ .description = "test if libkmod return correct initstate for builtin module from name",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-initstate",
+ [TC_UNAME_R] = "4.4.4",
+ },
+ .need_spawn = true);
+
+
+
+
+TESTSUITE_MAIN();
diff --git a/testsuite/test-list.c b/testsuite/test-list.c
new file mode 100644
index 0000000..535e8d7
--- /dev/null
+++ b/testsuite/test-list.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <libkmod/libkmod-internal.h>
+
+/* FIXME: hack, change name so we don't clash */
+#undef ERR
+#include "testsuite.h"
+
+static int len(struct kmod_list *list)
+{
+ int count = 0;
+ struct kmod_list *l;
+ kmod_list_foreach(l, list)
+ count++;
+ return count;
+}
+
+
+static int test_list_last(const struct test *t)
+{
+ struct kmod_list *list = NULL, *last;
+ int i;
+ const char *v[] = { "v1", "v2", "v3", "v4", "v5" };
+ const int N = ARRAY_SIZE(v);
+
+ for (i = 0; i < N; i++)
+ list = kmod_list_append(list, v[i]);
+ assert_return(len(list) == N, EXIT_FAILURE);
+
+ last = kmod_list_last(list);
+ assert_return(last->data == v[N - 1], EXIT_FAILURE);
+
+ return 0;
+}
+DEFINE_TEST(test_list_last,
+ .description = "test for the last element of a list");
+
+
+static int test_list_prev(const struct test *t)
+{
+ struct kmod_list *list = NULL, *l, *p;
+ int i;
+ const char *v[] = { "v1", "v2", "v3", "v4", "v5" };
+ const int N = ARRAY_SIZE(v);
+
+ l = kmod_list_prev(list, list);
+ assert_return(l == NULL, EXIT_FAILURE);
+
+ for (i = 0; i < N; i++)
+ list = kmod_list_append(list, v[i]);
+
+ l = kmod_list_prev(list, list);
+ assert_return(l == NULL, EXIT_FAILURE);
+
+ l = list;
+ for (i = 0; i < N - 1; i++) {
+ l = kmod_list_next(list, l);
+ p = kmod_list_prev(list, l);
+ assert_return(p->data == v[i], EXIT_FAILURE);
+ }
+
+ return 0;
+}
+DEFINE_TEST(test_list_prev,
+ .description = "test list prev");
+
+
+static int test_list_remove_n_latest(const struct test *t)
+{
+ struct kmod_list *list = NULL, *l;
+ int i;
+ const char *v[] = { "v1", "v2", "v3", "v4", "v5" };
+ const int N = ARRAY_SIZE(v), M = N / 2;
+
+ for (i = 0; i < N; i++)
+ list = kmod_list_append(list, v[i]);
+ assert_return(len(list) == N, EXIT_FAILURE);
+
+ list = kmod_list_remove_n_latest(list, M);
+ assert_return(len(list) == N - M, EXIT_FAILURE);
+
+ i = 0;
+ kmod_list_foreach (l, list) {
+ assert_return(l->data == v[i], EXIT_FAILURE);
+ i++;
+ }
+
+ return 0;
+}
+DEFINE_TEST(test_list_remove_n_latest,
+ .description = "test list function to remove n latest elements");
+
+
+static int test_list_remove_data(const struct test *t)
+{
+ struct kmod_list *list = NULL, *l;
+ int i;
+ const char *v[] = { "v1", "v2", "v3", "v4", "v5" }, *removed;
+ const int N = ARRAY_SIZE(v);
+
+ for (i = 0; i < N; i++)
+ list = kmod_list_append(list, v[i]);
+
+ removed = v[N / 2];
+ list = kmod_list_remove_data(list, removed);
+ assert_return(len(list) == N - 1, EXIT_FAILURE);
+
+ kmod_list_foreach (l, list)
+ assert_return(l->data != removed, EXIT_FAILURE);
+
+ return 0;
+}
+DEFINE_TEST(test_list_remove_data,
+ .description = "test list function to remove element by data");
+
+
+static int test_list_append_list(const struct test *t)
+{
+ struct kmod_list *a = NULL, *b = NULL, *c, *l;
+ int i;
+ const char *v[] = { "v1", "v2", "v3", "v4", "v5" };
+ const int N = ARRAY_SIZE(v), M = N / 2;
+
+ for (i = 0; i < M; i++)
+ a = kmod_list_append(a, v[i]);
+ assert_return(len(a) == M, EXIT_FAILURE);
+
+ for (i = M; i < N; i++)
+ b = kmod_list_append(b, v[i]);
+ assert_return(len(b) == N - M, EXIT_FAILURE);
+
+ a = kmod_list_append_list(a, NULL);
+ assert_return(len(a) == M, EXIT_FAILURE);
+
+ b = kmod_list_append_list(NULL, b);
+ assert_return(len(b) == N - M, EXIT_FAILURE);
+
+ c = kmod_list_append_list(a, b);
+ assert_return(len(c) == N, EXIT_FAILURE);
+
+ i = 0;
+ kmod_list_foreach (l, c) {
+ assert_return(l->data == v[i], EXIT_FAILURE);
+ i++;
+ }
+
+ return 0;
+}
+DEFINE_TEST(test_list_append_list,
+ .description = "test list function to append another list");
+
+
+static int test_list_insert_before(const struct test *t)
+{
+ struct kmod_list *list = NULL, *l;
+ const char *v1 = "v1", *v2 = "v2", *v3 = "v3", *vx = "vx";
+
+ list = kmod_list_insert_before(list, v3);
+ assert_return(len(list) == 1, EXIT_FAILURE);
+
+ list = kmod_list_insert_before(list, v2);
+ list = kmod_list_insert_before(list, v1);
+ assert_return(len(list) == 3, EXIT_FAILURE);
+
+ l = list;
+ assert_return(l->data == v1, EXIT_FAILURE);
+
+ l = kmod_list_next(list, l);
+ assert_return(l->data == v2, EXIT_FAILURE);
+
+ l = kmod_list_insert_before(l, vx);
+ assert_return(len(list) == 4, EXIT_FAILURE);
+ assert_return(l->data == vx, EXIT_FAILURE);
+
+ l = kmod_list_next(list, l);
+ assert_return(l->data == v2, EXIT_FAILURE);
+
+ l = kmod_list_next(list, l);
+ assert_return(l->data == v3, EXIT_FAILURE);
+
+ return 0;
+}
+DEFINE_TEST(test_list_insert_before,
+ .description = "test list function to insert before element");
+
+
+static int test_list_insert_after(const struct test *t)
+{
+ struct kmod_list *list = NULL, *l;
+ const char *v1 = "v1", *v2 = "v2", *v3 = "v3", *vx = "vx";
+
+ list = kmod_list_insert_after(list, v1);
+ assert_return(len(list) == 1, EXIT_FAILURE);
+
+ list = kmod_list_insert_after(list, v3);
+ list = kmod_list_insert_after(list, v2);
+ assert_return(len(list) == 3, EXIT_FAILURE);
+
+ l = list;
+ assert_return(l->data == v1, EXIT_FAILURE);
+
+ l = kmod_list_insert_after(l, vx);
+ assert_return(len(list) == 4, EXIT_FAILURE);
+ assert_return(l->data == v1, EXIT_FAILURE);
+
+ l = kmod_list_next(list, l);
+ assert_return(l->data == vx, EXIT_FAILURE);
+
+ l = kmod_list_next(list, l);
+ assert_return(l->data == v2, EXIT_FAILURE);
+
+ l = kmod_list_next(list, l);
+ assert_return(l->data == v3, EXIT_FAILURE);
+
+ return 0;
+}
+DEFINE_TEST(test_list_insert_after,
+ .description = "test list function to insert after element");
+
+TESTSUITE_MAIN();
diff --git a/testsuite/test-loaded.c b/testsuite/test-loaded.c
new file mode 100644
index 0000000..9d5814f
--- /dev/null
+++ b/testsuite/test-loaded.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2012-2013 ProFUSION embedded systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libkmod/libkmod.h>
+
+#include "testsuite.h"
+
+static int loaded_1(const struct test *t)
+{
+ struct kmod_ctx *ctx;
+ const char *null_config = NULL;
+ struct kmod_list *list, *itr;
+ int err;
+
+ ctx = kmod_new(NULL, &null_config);
+ if (ctx == NULL)
+ exit(EXIT_FAILURE);
+
+ err = kmod_module_new_from_loaded(ctx, &list);
+ if (err < 0) {
+ fprintf(stderr, "%s\n", strerror(-err));
+ kmod_unref(ctx);
+ exit(EXIT_FAILURE);
+ }
+
+ printf("Module Size Used by\n");
+
+ kmod_list_foreach(itr, list) {
+ struct kmod_module *mod = kmod_module_get_module(itr);
+ const char *name = kmod_module_get_name(mod);
+ int use_count = kmod_module_get_refcnt(mod);
+ long size = kmod_module_get_size(mod);
+ struct kmod_list *holders, *hitr;
+ int first = 1;
+
+ printf("%-19s %8ld %d ", name, size, use_count);
+ holders = kmod_module_get_holders(mod);
+ kmod_list_foreach(hitr, holders) {
+ struct kmod_module *hm = kmod_module_get_module(hitr);
+
+ if (!first)
+ putchar(',');
+ else
+ first = 0;
+
+ fputs(kmod_module_get_name(hm), stdout);
+ kmod_module_unref(hm);
+ }
+ putchar('\n');
+ kmod_module_unref_list(holders);
+ kmod_module_unref(mod);
+ }
+ kmod_module_unref_list(list);
+
+ kmod_unref(ctx);
+
+ return EXIT_SUCCESS;
+}
+DEFINE_TEST(loaded_1,
+ .description = "check if list of module is created",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-loaded/",
+ },
+ .need_spawn = true,
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-loaded/correct.txt",
+ });
+
+TESTSUITE_MAIN();
diff --git a/testsuite/test-modinfo.c b/testsuite/test-modinfo.c
new file mode 100644
index 0000000..373dc95
--- /dev/null
+++ b/testsuite/test-modinfo.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2012-2013 ProFUSION embedded systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "testsuite.h"
+
+static const char *progname = ABS_TOP_BUILDDIR "/tools/modinfo";
+
+#define DEFINE_MODINFO_TEST(_field, _flavor, ...) \
+static noreturn int test_modinfo_##_field(const struct test *t) \
+{ \
+ const char *const args[] = { \
+ progname, "-F", #_field ,\
+ __VA_ARGS__ , \
+ NULL, \
+ }; \
+ test_spawn_prog(progname, args); \
+ exit(EXIT_FAILURE); \
+} \
+DEFINE_TEST(test_modinfo_##_field, \
+ .description = "check " #_field " output of modinfo for different architectures", \
+ .config = { \
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modinfo/", \
+ }, \
+ .output = { \
+ .out = TESTSUITE_ROOTFS "test-modinfo/correct-" #_field #_flavor ".txt", \
+ })
+
+#define DEFINE_MODINFO_GENERIC_TEST(_field) \
+ DEFINE_MODINFO_TEST(_field, , \
+ "/mod-simple-i386.ko", \
+ "/mod-simple-x86_64.ko", \
+ "/mod-simple-sparc64.ko")
+
+#ifdef ENABLE_OPENSSL
+#define DEFINE_MODINFO_SIGN_TEST(_field) \
+ DEFINE_MODINFO_TEST(_field, -openssl, \
+ "/mod-simple-sha1.ko", \
+ "/mod-simple-sha256.ko", \
+ "/mod-simple-pkcs7.ko")
+#else
+#define DEFINE_MODINFO_SIGN_TEST(_field) \
+ DEFINE_MODINFO_TEST(_field, , \
+ "/mod-simple-sha1.ko", \
+ "/mod-simple-sha256.ko", \
+ "/mod-simple-pkcs7.ko")
+#endif
+
+DEFINE_MODINFO_GENERIC_TEST(filename);
+DEFINE_MODINFO_GENERIC_TEST(author);
+DEFINE_MODINFO_GENERIC_TEST(license);
+DEFINE_MODINFO_GENERIC_TEST(description);
+DEFINE_MODINFO_GENERIC_TEST(parm);
+DEFINE_MODINFO_GENERIC_TEST(depends);
+
+DEFINE_MODINFO_SIGN_TEST(signer);
+DEFINE_MODINFO_SIGN_TEST(sig_key);
+DEFINE_MODINFO_SIGN_TEST(sig_hashalgo);
+
+#if 0
+static noreturn int test_modinfo_signature(const struct test *t)
+{
+ const char *const args[] = {
+ progname,
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(test_modinfo_signature,
+ .description = "check signatures are correct for modinfo is correct for i686, ppc64, s390x and x86_64",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modinfo/",
+ },
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-modinfo/correct.txt",
+ });
+#endif
+
+static noreturn int test_modinfo_external(const struct test *t)
+{
+ const char *const args[] = {
+ progname, "-F", "filename",
+ "mod-simple",
+ NULL,
+ };
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(test_modinfo_external,
+ .description = "check if modinfo finds external module",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modinfo/external",
+ [TC_UNAME_R] = "4.4.4",
+ },
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-modinfo/correct-external.txt",
+ })
+
+TESTSUITE_MAIN();
diff --git a/testsuite/test-modprobe.c b/testsuite/test-modprobe.c
new file mode 100644
index 0000000..309f3e3
--- /dev/null
+++ b/testsuite/test-modprobe.c
@@ -0,0 +1,469 @@
+/*
+ * Copyright (C) 2012-2013 ProFUSION embedded systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "testsuite.h"
+
+static noreturn int modprobe_show_depends(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe";
+ const char *const args[] = {
+ progname,
+ "--show-depends", "mod-loop-a",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(modprobe_show_depends,
+ .description = "check if output for modprobe --show-depends is correct for loaded modules",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/show-depends",
+ },
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-modprobe/show-depends/correct.txt",
+ });
+
+static noreturn int modprobe_show_depends2(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe";
+ const char *const args[] = {
+ progname,
+ "--show-depends", "mod-simple",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(modprobe_show_depends2,
+ .description = "check if output for modprobe --show-depends is correct",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/show-depends",
+ },
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-modprobe/show-depends/correct-mod-simple.txt",
+ });
+
+
+static noreturn int modprobe_show_alias_to_none(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe";
+ const char *const args[] = {
+ progname,
+ "--show-depends", "--ignore-install", "--quiet", "mod-simple",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(modprobe_show_alias_to_none,
+ .description = "check if modprobe --show-depends doesn't explode with an alias to nothing",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/alias-to-none",
+ },
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-modprobe/alias-to-none/correct.txt",
+ },
+ .modules_loaded = "",
+ );
+
+
+static noreturn int modprobe_show_exports(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe";
+ const char *const args[] = {
+ progname,
+ "--show-exports", "--quiet", "/mod-loop-a.ko",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(modprobe_show_exports,
+ .description = "check if modprobe --show-depends doesn't explode with an alias to nothing",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/show-exports",
+ },
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-modprobe/show-exports/correct.txt",
+ .regex = true,
+ });
+
+
+static noreturn int modprobe_builtin(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe";
+ const char *const args[] = {
+ progname,
+ "unix",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(modprobe_builtin,
+ .description = "check if modprobe return 0 for builtin",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/builtin",
+ });
+
+static noreturn int modprobe_builtin_lookup_only(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe";
+ const char *const args[] = {
+ progname,
+ "-R", "unix",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(modprobe_builtin_lookup_only,
+ .description = "check if modprobe -R correctly returns the builtin module",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/builtin",
+ },
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-modprobe/builtin/correct.txt",
+ });
+
+static noreturn int modprobe_softdep_loop(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe";
+ const char *const args[] = {
+ progname,
+ "mod-loop-b",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(modprobe_softdep_loop,
+ .description = "check if modprobe breaks softdep loop",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/softdep-loop",
+ [TC_INIT_MODULE_RETCODES] = "",
+ },
+ .modules_loaded = "mod-loop-a,mod-loop-b",
+ );
+
+static noreturn int modprobe_install_cmd_loop(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe";
+ const char *const args[] = {
+ progname,
+ "mod-loop-a",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(modprobe_install_cmd_loop,
+ .description = "check if modprobe breaks install-commands loop",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/install-cmd-loop",
+ [TC_INIT_MODULE_RETCODES] = "",
+ },
+ .env_vars = (const struct keyval[]) {
+ { "MODPROBE", ABS_TOP_BUILDDIR "/tools/modprobe" },
+ { }
+ },
+ .modules_loaded = "mod-loop-b,mod-loop-a",
+ );
+
+static noreturn int modprobe_param_kcmdline_show_deps(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe";
+ const char *const args[] = {
+ progname,
+ "--show-depends", "mod-simple",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(modprobe_param_kcmdline_show_deps,
+ .description = "check if params from kcmdline are passed to (f)init_module call",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline",
+ },
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline/correct.txt",
+ },
+ .modules_loaded = "",
+ );
+
+static noreturn int modprobe_param_kcmdline(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe";
+ const char *const args[] = {
+ progname,
+ "-c",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST_WITH_FUNC(modprobe_param_kcmdline2, modprobe_param_kcmdline,
+ .description = "check if params with no value are parsed correctly from kcmdline",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline2",
+ },
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline2/correct.txt",
+ },
+ .modules_loaded = "",
+ );
+
+DEFINE_TEST_WITH_FUNC(modprobe_param_kcmdline3, modprobe_param_kcmdline,
+ .description = "check if unrelated strings in kcmdline are correctly ignored",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline3",
+ },
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline3/correct.txt",
+ },
+ .modules_loaded = "",
+ );
+
+DEFINE_TEST_WITH_FUNC(modprobe_param_kcmdline4, modprobe_param_kcmdline,
+ .description = "check if unrelated strings in kcmdline are correctly ignored",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline4",
+ },
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline4/correct.txt",
+ },
+ .modules_loaded = "",
+ );
+
+DEFINE_TEST_WITH_FUNC(modprobe_param_kcmdline5, modprobe_param_kcmdline,
+ .description = "check if params with spaces are parsed correctly from kcmdline",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline5",
+ },
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline5/correct.txt",
+ },
+ .modules_loaded = "",
+ );
+
+DEFINE_TEST_WITH_FUNC(modprobe_param_kcmdline6, modprobe_param_kcmdline,
+ .description = "check if dots on other parts of kcmdline don't confuse our parser",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline6",
+ },
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline6/correct.txt",
+ },
+ .modules_loaded = "",
+ );
+
+DEFINE_TEST_WITH_FUNC(modprobe_param_kcmdline7, modprobe_param_kcmdline,
+ .description = "check if dots on other parts of kcmdline don't confuse our parser",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline7",
+ },
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline7/correct.txt",
+ },
+ .modules_loaded = "",
+ );
+
+DEFINE_TEST_WITH_FUNC(modprobe_param_kcmdline8, modprobe_param_kcmdline,
+ .description = "check if dots on other parts of kcmdline don't confuse our parser",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline8",
+ },
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-modprobe/module-param-kcmdline8/correct.txt",
+ },
+ .modules_loaded = "",
+ );
+
+
+static noreturn int modprobe_force(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe";
+ const char *const args[] = {
+ progname,
+ "--force", "mod-simple",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(modprobe_force,
+ .description = "check modprobe --force",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/force",
+ [TC_INIT_MODULE_RETCODES] = "",
+ },
+ .modules_loaded = "mod-simple",
+ );
+
+static noreturn int modprobe_oldkernel(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe";
+ const char *const args[] = {
+ progname,
+ "mod-simple",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(modprobe_oldkernel,
+ .description = "check modprobe with kernel without finit_module()",
+ .config = {
+ [TC_UNAME_R] = "3.3.3",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/oldkernel",
+ [TC_INIT_MODULE_RETCODES] = "",
+ },
+ .modules_loaded = "mod-simple",
+ );
+
+static noreturn int modprobe_oldkernel_force(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe";
+ const char *const args[] = {
+ progname,
+ "--force", "mod-simple",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(modprobe_oldkernel_force,
+ .description = "check modprobe --force with kernel without finit_module()",
+ .config = {
+ [TC_UNAME_R] = "3.3.3",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/oldkernel-force",
+ [TC_INIT_MODULE_RETCODES] = "",
+ },
+ .modules_loaded = "mod-simple",
+ );
+
+static noreturn int modprobe_external(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe";
+ const char *const args[] = {
+ progname,
+ "mod-simple",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(modprobe_external,
+ .description = "check modprobe able to load external module",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/external",
+ [TC_INIT_MODULE_RETCODES] = "",
+ },
+ .modules_loaded = "mod-simple",
+ );
+
+static noreturn int modprobe_module_from_abspath(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe";
+ const char *const args[] = {
+ progname,
+ "/home/foo/mod-simple.ko",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(modprobe_module_from_abspath,
+ .description = "check modprobe able to load module given as an absolute path",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/module-from-abspath",
+ [TC_INIT_MODULE_RETCODES] = "",
+ },
+ .modules_loaded = "mod-simple",
+ );
+
+static noreturn int modprobe_module_from_relpath(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/modprobe";
+ const char *const args[] = {
+ progname,
+ "./mod-simple.ko",
+ NULL,
+ };
+
+ if (chdir("/home/foo") != 0) {
+ perror("failed to change into /home/foo");
+ exit(EXIT_FAILURE);
+ }
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(modprobe_module_from_relpath,
+ .description = "check modprobe able to load module given as a relative path",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-modprobe/module-from-relpath",
+ [TC_INIT_MODULE_RETCODES] = "",
+ },
+ .need_spawn = true,
+ .modules_loaded = "mod-simple",
+ );
+
+TESTSUITE_MAIN();
diff --git a/testsuite/test-new-module.c b/testsuite/test-new-module.c
new file mode 100644
index 0000000..9872b78
--- /dev/null
+++ b/testsuite/test-new-module.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2012-2013 ProFUSION embedded systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libkmod/libkmod.h>
+
+#include "testsuite.h"
+
+static int from_name(const struct test *t)
+{
+ static const char *const modnames[] = {
+ "ext4",
+ "balbalbalbbalbalbalbalbalbalbal",
+ "snd-hda-intel",
+ "snd-timer",
+ "iTCO_wdt",
+ NULL,
+ };
+ const char *const *p;
+ struct kmod_ctx *ctx;
+ struct kmod_module *mod;
+ const char *null_config = NULL;
+ int err;
+
+ ctx = kmod_new(NULL, &null_config);
+ if (ctx == NULL)
+ exit(EXIT_FAILURE);
+
+ for (p = modnames; p != NULL; p++) {
+ err = kmod_module_new_from_name(ctx, *p, &mod);
+ if (err < 0)
+ exit(EXIT_SUCCESS);
+
+ printf("modname: %s\n", kmod_module_get_name(mod));
+ kmod_module_unref(mod);
+ }
+
+ kmod_unref(ctx);
+
+ return EXIT_SUCCESS;
+}
+DEFINE_TEST(from_name,
+ .description = "check if module names are parsed correctly",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-new-module/from_name/",
+ },
+ .need_spawn = true,
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-new-module/from_name/correct.txt",
+ });
+
+static int from_alias(const struct test *t)
+{
+ static const char *const modnames[] = {
+ "ext4.*",
+ NULL,
+ };
+ const char *const *p;
+ struct kmod_ctx *ctx;
+ int err;
+
+ ctx = kmod_new(NULL, NULL);
+ if (ctx == NULL)
+ exit(EXIT_FAILURE);
+
+ for (p = modnames; p != NULL; p++) {
+ struct kmod_list *l, *list = NULL;
+
+ err = kmod_module_new_from_lookup(ctx, *p, &list);
+ if (err < 0)
+ exit(EXIT_SUCCESS);
+
+ kmod_list_foreach(l, list) {
+ struct kmod_module *m;
+ m = kmod_module_get_module(l);
+
+ printf("modname: %s\n", kmod_module_get_name(m));
+ kmod_module_unref(m);
+ }
+ kmod_module_unref_list(list);
+ }
+
+ kmod_unref(ctx);
+
+ return EXIT_SUCCESS;
+}
+DEFINE_TEST(from_alias,
+ .description = "check if aliases are parsed correctly",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-new-module/from_alias/",
+ },
+ .need_spawn = true,
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-new-module/from_alias/correct.txt",
+ });
+
+TESTSUITE_MAIN();
diff --git a/testsuite/test-scratchbuf.c b/testsuite/test-scratchbuf.c
new file mode 100644
index 0000000..6d86957
--- /dev/null
+++ b/testsuite/test-scratchbuf.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <shared/scratchbuf.h>
+
+#include "testsuite.h"
+
+static int test_scratchbuf_onlystack(const struct test *t)
+{
+ struct scratchbuf sbuf;
+ const char *smallstr = "xyz";
+ char buf[3 + 2];
+ char buf2[3 + 1];
+
+ scratchbuf_init(&sbuf, buf, sizeof(buf));
+ assert_return(scratchbuf_alloc(&sbuf, strlen(smallstr) + 1) == 0, EXIT_FAILURE);
+ assert_return(sbuf.need_free == false, EXIT_FAILURE);
+ scratchbuf_release(&sbuf);
+
+ scratchbuf_init(&sbuf, buf2, sizeof(buf2));
+ assert_return(scratchbuf_alloc(&sbuf, strlen(smallstr) + 1) == 0, EXIT_FAILURE);
+ assert_return(sbuf.need_free == false, EXIT_FAILURE);
+ scratchbuf_release(&sbuf);
+
+ memcpy(scratchbuf_str(&sbuf), smallstr, strlen(smallstr) + 1);
+ assert_return(strcmp(scratchbuf_str(&sbuf), smallstr) == 0, EXIT_FAILURE);
+
+ return 0;
+}
+DEFINE_TEST(test_scratchbuf_onlystack,
+ .description = "test scratchbuf for buffer on stack only");
+
+
+static int test_scratchbuf_heap(const struct test *t)
+{
+ struct scratchbuf sbuf;
+ const char *smallstr = "xyz";
+ const char *largestr = "xyzxyzxyz";
+ const char *largestr2 = "xyzxyzxyzxyzxyz";
+ char buf[3 + 1];
+
+ scratchbuf_init(&sbuf, buf, sizeof(buf));
+
+ /* Initially only on stack */
+ assert_return(scratchbuf_alloc(&sbuf, strlen(smallstr) + 1) == 0, EXIT_FAILURE);
+ assert_return(sbuf.need_free == false, EXIT_FAILURE);
+ memcpy(scratchbuf_str(&sbuf), smallstr, strlen(smallstr) + 1);
+
+ /* Grow once to heap */
+ assert_return(scratchbuf_alloc(&sbuf, strlen(largestr) + 1) == 0, EXIT_FAILURE);
+ assert_return(sbuf.need_free == true, EXIT_FAILURE);
+ assert_return(sbuf.size == strlen(largestr) + 1, EXIT_FAILURE);
+ assert_return(strcmp(scratchbuf_str(&sbuf), smallstr) == 0, EXIT_FAILURE);
+ memcpy(scratchbuf_str(&sbuf), largestr, strlen(largestr) + 1);
+ assert_return(strcmp(scratchbuf_str(&sbuf), largestr) == 0, EXIT_FAILURE);
+
+ /* Grow again - realloc should take place */
+ assert_return(scratchbuf_alloc(&sbuf, strlen(largestr2) + 1) == 0, EXIT_FAILURE);
+ assert_return(sbuf.need_free == true, EXIT_FAILURE);
+ assert_return(sbuf.size == strlen(largestr2) + 1, EXIT_FAILURE);
+ memcpy(scratchbuf_str(&sbuf), largestr2, strlen(largestr2) + 1);
+ assert_return(strcmp(scratchbuf_str(&sbuf), largestr2) == 0, EXIT_FAILURE);
+
+ scratchbuf_release(&sbuf);
+
+ return 0;
+}
+DEFINE_TEST(test_scratchbuf_heap,
+ .description = "test scratchbuf for buffer on that grows to heap");
+
+TESTSUITE_MAIN();
diff --git a/testsuite/test-strbuf.c b/testsuite/test-strbuf.c
new file mode 100644
index 0000000..c98c91d
--- /dev/null
+++ b/testsuite/test-strbuf.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2014 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <shared/strbuf.h>
+#include <shared/util.h>
+
+#include "testsuite.h"
+
+static const char *TEXT =
+ "this is a very long test that is longer than the size we initially se in the strbuf";
+
+static int test_strbuf_pushchar(const struct test *t)
+{
+ struct strbuf buf;
+ char *result1, *result2;
+ const char *c;
+
+ strbuf_init(&buf);
+
+ for (c = TEXT; *c != '\0'; c++)
+ strbuf_pushchar(&buf, *c);
+
+ result1 = (char *) strbuf_str(&buf);
+ assert_return(result1 == buf.bytes, EXIT_FAILURE);
+ assert_return(streq(result1, TEXT), EXIT_FAILURE);
+ result1 = strdup(result1);
+
+ result2 = strbuf_steal(&buf);
+ assert_return(streq(result1, result2), EXIT_FAILURE);
+
+ free(result1);
+ free(result2);
+
+ return 0;
+}
+DEFINE_TEST(test_strbuf_pushchar,
+ .description = "test strbuf_{pushchar, str, steal}");
+
+static int test_strbuf_pushchars(const struct test *t)
+{
+ struct strbuf buf;
+ char *result1, *saveptr = NULL, *str, *result2;
+ const char *c;
+ int lastwordlen = 0;
+
+ strbuf_init(&buf);
+ str = strdup(TEXT);
+ for (c = strtok_r(str, " ", &saveptr); c != NULL;
+ c = strtok_r(NULL, " ", &saveptr)) {
+ strbuf_pushchars(&buf, c);
+ strbuf_pushchar(&buf, ' ');
+ lastwordlen = strlen(c);
+ }
+
+ strbuf_popchar(&buf);
+ result1 = (char *) strbuf_str(&buf);
+ assert_return(result1 == buf.bytes, EXIT_FAILURE);
+ assert_return(streq(result1, TEXT), EXIT_FAILURE);
+
+ strbuf_popchars(&buf, lastwordlen);
+ result2 = strbuf_steal(&buf);
+ assert_return(!streq(TEXT, result2), EXIT_FAILURE);
+ assert_return(strncmp(TEXT, result2, strlen(TEXT) - lastwordlen) == 0,
+ EXIT_FAILURE);
+ assert_return(result2[strlen(TEXT) - lastwordlen] == '\0',
+ EXIT_FAILURE);
+
+ free(str);
+ free(result2);
+
+ return 0;
+}
+DEFINE_TEST(test_strbuf_pushchars,
+ .description = "test strbuf_{pushchars, popchar, popchars}");
+
+
+TESTSUITE_MAIN();
diff --git a/testsuite/test-testsuite.c b/testsuite/test-testsuite.c
new file mode 100644
index 0000000..c77c4bb
--- /dev/null
+++ b/testsuite/test-testsuite.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2012-2013 ProFUSION embedded systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+
+#include <shared/util.h>
+
+#include <libkmod/libkmod.h>
+
+#include "testsuite.h"
+
+
+#define TEST_UNAME "4.0.20-kmod"
+static noreturn int testsuite_uname(const struct test *t)
+{
+ struct utsname u;
+ int err = uname(&u);
+
+ if (err < 0)
+ exit(EXIT_FAILURE);
+
+ if (!streq(u.release, TEST_UNAME)) {
+ char *ldpreload = getenv("LD_PRELOAD");
+ ERR("u.release=%s should be %s\n", u.release, TEST_UNAME);
+ ERR("LD_PRELOAD=%s\n", ldpreload);
+ exit(EXIT_FAILURE);
+ }
+
+ exit(EXIT_SUCCESS);
+}
+DEFINE_TEST(testsuite_uname,
+ .description = "test if trap to uname() works",
+ .config = {
+ [TC_UNAME_R] = TEST_UNAME,
+ },
+ .need_spawn = true);
+
+static int testsuite_rootfs_fopen(const struct test *t)
+{
+ FILE *fp;
+ char s[100];
+ int n;
+
+ fp = fopen(MODULE_DIRECTORY "/a", "r");
+ if (fp == NULL)
+ return EXIT_FAILURE;;
+
+ n = fscanf(fp, "%s", s);
+ if (n != 1)
+ return EXIT_FAILURE;
+
+ if (!streq(s, "kmod-test-chroot-works"))
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
+}
+DEFINE_TEST(testsuite_rootfs_fopen,
+ .description = "test if rootfs works - fopen()",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-rootfs/",
+ },
+ .need_spawn = true);
+
+static int testsuite_rootfs_open(const struct test *t)
+{
+ char buf[100];
+ int fd, done;
+
+ fd = open(MODULE_DIRECTORY "/a", O_RDONLY);
+ if (fd < 0)
+ return EXIT_FAILURE;
+
+ for (done = 0;;) {
+ int r = read(fd, buf + done, sizeof(buf) - 1 - done);
+ if (r == 0)
+ break;
+ if (r == -EAGAIN)
+ continue;
+
+ done += r;
+ }
+
+ buf[done] = '\0';
+
+ if (!streq(buf, "kmod-test-chroot-works\n"))
+ return EXIT_FAILURE;
+
+ return EXIT_SUCCESS;
+}
+DEFINE_TEST(testsuite_rootfs_open,
+ .description = "test if rootfs works - open()",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-rootfs/",
+ },
+ .need_spawn = true);
+
+static int testsuite_rootfs_stat_access(const struct test *t)
+{
+ struct stat st;
+
+ if (access(MODULE_DIRECTORY "/a", F_OK) < 0) {
+ ERR("access failed: %m\n");
+ return EXIT_FAILURE;
+ }
+
+ if (stat(MODULE_DIRECTORY "/a", &st) < 0) {
+ ERR("stat failed: %m\n");
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+DEFINE_TEST(testsuite_rootfs_stat_access,
+ .description = "test if rootfs works - stat() and access()",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-rootfs/",
+ },
+ .need_spawn = true);
+
+static int testsuite_rootfs_opendir(const struct test *t)
+{
+ DIR *d;
+
+ d = opendir("/testdir");
+ if (d == NULL) {
+ ERR("opendir failed: %m\n");
+ return EXIT_FAILURE;
+ }
+
+ closedir(d);
+ return EXIT_SUCCESS;
+}
+DEFINE_TEST(testsuite_rootfs_opendir,
+ .description = "test if rootfs works - opendir()",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-rootfs/",
+ },
+ .need_spawn = true);
+
+TESTSUITE_MAIN();
diff --git a/testsuite/test-tools.c b/testsuite/test-tools.c
new file mode 100644
index 0000000..4a9ee9b
--- /dev/null
+++ b/testsuite/test-tools.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "testsuite.h"
+
+static noreturn int kmod_tool_insert(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/kmod";
+ const char *const args[] = {
+ progname,
+ "insert", "mod-simple",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(kmod_tool_insert,
+ .description = "check kmod insert",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-tools/insert",
+ [TC_INIT_MODULE_RETCODES] = "",
+ },
+ .modules_loaded = "mod-simple",
+ );
+
+static noreturn int kmod_tool_remove(const struct test *t)
+{
+ const char *progname = ABS_TOP_BUILDDIR "/tools/kmod";
+ const char *const args[] = {
+ progname,
+ "remove", "mod-simple",
+ NULL,
+ };
+
+ test_spawn_prog(progname, args);
+ exit(EXIT_FAILURE);
+}
+DEFINE_TEST(kmod_tool_remove,
+ .description = "check kmod remove",
+ .config = {
+ [TC_UNAME_R] = "4.4.4",
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-tools/remove",
+ [TC_DELETE_MODULE_RETCODES] = "",
+ },
+ );
+
+TESTSUITE_MAIN();
diff --git a/testsuite/test-util.c b/testsuite/test-util.c
new file mode 100644
index 0000000..e3243e8
--- /dev/null
+++ b/testsuite/test-util.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2012-2013 ProFUSION embedded systems
+ * Copyright (C) 2012 Pedro Pedruzzi
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <shared/util.h>
+
+#include "testsuite.h"
+
+static int alias_1(const struct test *t)
+{
+ static const char *const input[] = {
+ "test1234",
+ "test[abcfoobar]2211",
+ "bar[aaa][bbbb]sss",
+ "kmod[p.b]lib",
+ "[az]1234[AZ]",
+ NULL,
+ };
+
+ char buf[PATH_MAX];
+ size_t len;
+ const char *const *alias;
+
+ for (alias = input; *alias != NULL; alias++) {
+ int ret;
+
+ ret = alias_normalize(*alias, buf, &len);
+ printf("input %s\n", *alias);
+ printf("return %d\n", ret);
+
+ if (ret == 0) {
+ printf("len %zu\n", len);
+ printf("output %s\n", buf);
+ }
+
+ printf("\n");
+ }
+
+ return EXIT_SUCCESS;
+}
+DEFINE_TEST(alias_1,
+ .description = "check if alias_normalize does the right thing",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-util/",
+ },
+ .need_spawn = true,
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-util/alias-correct.txt",
+ });
+
+static int test_freadline_wrapped(const struct test *t)
+{
+ FILE *fp = fopen("/freadline_wrapped-input.txt", "re");
+
+ if (!fp)
+ return EXIT_FAILURE;
+
+ while (!feof(fp) && !ferror(fp)) {
+ unsigned int num = 0;
+ char *s = freadline_wrapped(fp, &num);
+ if (!s)
+ break;
+ puts(s);
+ free(s);
+ printf("%u\n", num);
+ }
+
+ fclose(fp);
+ return EXIT_SUCCESS;
+}
+DEFINE_TEST(test_freadline_wrapped,
+ .description = "check if freadline_wrapped() does the right thing",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-util/",
+ },
+ .need_spawn = true,
+ .output = {
+ .out = TESTSUITE_ROOTFS "test-util/freadline_wrapped-correct.txt",
+ });
+
+static int test_strchr_replace(const struct test *t)
+{
+ _cleanup_free_ char *s = strdup("this is a test string");
+ const char *res = "thiC iC a teCt Ctring";
+
+ strchr_replace(s, 's', 'C');
+ assert_return(streq(s, res), EXIT_FAILURE);
+
+ return EXIT_SUCCESS;
+}
+DEFINE_TEST(test_strchr_replace,
+ .description = "check implementation of strchr_replace()",
+ .need_spawn = false,
+ );
+
+static int test_underscores(const struct test *t)
+{
+ struct teststr {
+ char *val;
+ const char *res;
+ } teststr[] = {
+ { strdup("aa-bb-cc_"), "aa_bb_cc_" },
+ { strdup("-aa-bb-cc-"), "_aa_bb_cc_" },
+ { strdup("-aa[-bb-]cc-"), "_aa[-bb-]cc_" },
+ { strdup("-aa-[bb]-cc-"), "_aa_[bb]_cc_" },
+ { strdup("-aa-[b-b]-cc-"), "_aa_[b-b]_cc_" },
+ { strdup("-aa-b[-]b-cc"), "_aa_b[-]b_cc" },
+ { }
+ }, *iter;
+
+ for (iter = &teststr[0]; iter->val != NULL; iter++) {
+ _cleanup_free_ char *val = iter->val;
+ underscores(val);
+ assert_return(streq(val, iter->res), EXIT_FAILURE);
+ }
+
+ return EXIT_SUCCESS;
+}
+DEFINE_TEST(test_underscores,
+ .description = "check implementation of underscores()",
+ .need_spawn = false,
+ );
+
+static int test_path_ends_with_kmod_ext(const struct test *t)
+{
+ struct teststr {
+ const char *val;
+ bool res;
+ } teststr[] = {
+ { "/bla.ko", true },
+#ifdef ENABLE_ZLIB
+ { "/bla.ko.gz", true },
+#endif
+#ifdef ENABLE_XZ
+ { "/bla.ko.xz", true },
+#endif
+#ifdef ENABLE_ZSTD
+ { "/bla.ko.zst", true },
+#endif
+ { "/bla.ko.x", false },
+ { "/bla.ko.", false },
+ { "/bla.koz", false },
+ { "/b", false },
+ { }
+ }, *iter;
+
+ for (iter = &teststr[0]; iter->val != NULL; iter++) {
+ assert_return(path_ends_with_kmod_ext(iter->val,
+ strlen(iter->val)) == iter->res,
+ EXIT_FAILURE);
+ }
+
+ return EXIT_SUCCESS;
+}
+DEFINE_TEST(test_path_ends_with_kmod_ext,
+ .description = "check implementation of path_ends_with_kmod_ext()",
+ .need_spawn = false,
+ );
+
+#define TEST_WRITE_STR_SAFE_FILE "/write-str-safe"
+#define TEST_WRITE_STR_SAFE_PATH TESTSUITE_ROOTFS "test-util2/" TEST_WRITE_STR_SAFE_FILE
+static int test_write_str_safe(const struct test *t)
+{
+ const char *s = "test";
+ int fd;
+
+ fd = open(TEST_WRITE_STR_SAFE_FILE ".txt", O_CREAT|O_TRUNC|O_WRONLY, 0644);
+ assert_return(fd >= 0, EXIT_FAILURE);
+
+ write_str_safe(fd, s, strlen(s));
+ close(fd);
+
+ return EXIT_SUCCESS;
+}
+DEFINE_TEST(test_write_str_safe,
+ .description = "check implementation of write_str_safe()",
+ .config = {
+ [TC_ROOTFS] = TESTSUITE_ROOTFS "test-util2/",
+ },
+ .need_spawn = true,
+ .output = {
+ .files = (const struct keyval[]) {
+ { TEST_WRITE_STR_SAFE_PATH ".txt",
+ TEST_WRITE_STR_SAFE_PATH "-correct.txt" },
+ { }
+ },
+ });
+
+static int test_addu64_overflow(const struct test *t)
+{
+ uint64_t res;
+ bool overflow;
+
+ overflow = addu64_overflow(UINT64_MAX - 1, 1, &res);
+ assert_return(!overflow, EXIT_FAILURE);
+ assert_return(res == UINT64_MAX, EXIT_FAILURE);
+
+ overflow = addu64_overflow(UINT64_MAX, 1, &res);
+ assert_return(overflow, EXIT_FAILURE);
+
+ return EXIT_SUCCESS;
+}
+DEFINE_TEST(test_addu64_overflow,
+ .description = "check implementation of addu4_overflow()",
+ .need_spawn = false,
+ );
+
+
+static int test_backoff_time(const struct test *t)
+{
+ unsigned long long delta = 0;
+
+ /* Check exponential increments */
+ get_backoff_delta_msec(now_msec(), now_msec() + 10, &delta);
+ assert_return(delta == 1, EXIT_FAILURE);
+ get_backoff_delta_msec(now_msec(), now_msec() + 10, &delta);
+ assert_return(delta == 2, EXIT_FAILURE);
+ get_backoff_delta_msec(now_msec(), now_msec() + 10, &delta);
+ assert_return(delta == 4, EXIT_FAILURE);
+ get_backoff_delta_msec(now_msec(), now_msec() + 10, &delta);
+ assert_return(delta == 8, EXIT_FAILURE);
+
+ {
+ unsigned long long t0, tend;
+
+ /* Check tail */
+ delta = 4;
+ tend = now_msec() + 3;
+ t0 = tend - 10;
+ get_backoff_delta_msec(t0, tend, &delta);
+ assert_return(delta == 2, EXIT_FAILURE);
+ tend = now_msec() + 1;
+ t0 = tend - 9;
+ get_backoff_delta_msec(t0, tend, &delta);
+ assert_return(delta == 1, EXIT_FAILURE);
+ tend = now_msec();
+ t0 = tend - 10;
+ get_backoff_delta_msec(t0, tend, &delta);
+ assert_return(delta == 0, EXIT_FAILURE);
+ }
+
+ return EXIT_SUCCESS;
+}
+DEFINE_TEST(test_backoff_time,
+ .description = "check implementation of get_backoff_delta_msec()",
+ .need_spawn = false,
+ );
+
+
+TESTSUITE_MAIN();
diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c
new file mode 100644
index 0000000..318343a
--- /dev/null
+++ b/testsuite/testsuite.c
@@ -0,0 +1,1119 @@
+/*
+ * Copyright (C) 2012-2013 ProFUSION embedded systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <limits.h>
+#include <regex.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/epoll.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <shared/util.h>
+
+#include "testsuite.h"
+
+static const char *ANSI_HIGHLIGHT_GREEN_ON = "\x1B[1;32m";
+static const char *ANSI_HIGHLIGHT_YELLOW_ON = "\x1B[1;33m";
+static const char *ANSI_HIGHLIGHT_RED_ON = "\x1B[1;31m";
+static const char *ANSI_HIGHLIGHT_OFF = "\x1B[0m";
+
+static const char *progname;
+static int oneshot = 0;
+static const char options_short[] = "lhn";
+static const struct option options[] = {
+ { "list", no_argument, 0, 'l' },
+ { "help", no_argument, 0, 'h' },
+ { NULL, 0, 0, 0 }
+};
+
+#define OVERRIDE_LIBDIR ABS_TOP_BUILDDIR "/testsuite/.libs/"
+#define TEST_TIMEOUT_USEC 2 * USEC_PER_SEC
+
+static const struct {
+ const char *key;
+ const char *ldpreload;
+} env_config[_TC_LAST] = {
+ [TC_UNAME_R] = { S_TC_UNAME_R, OVERRIDE_LIBDIR "uname.so" },
+ [TC_ROOTFS] = { S_TC_ROOTFS, OVERRIDE_LIBDIR "path.so" },
+ [TC_INIT_MODULE_RETCODES] = { S_TC_INIT_MODULE_RETCODES, OVERRIDE_LIBDIR "init_module.so" },
+ [TC_DELETE_MODULE_RETCODES] = { S_TC_DELETE_MODULE_RETCODES, OVERRIDE_LIBDIR "delete_module.so" },
+};
+
+static void help(void)
+{
+ const struct option *itr;
+ const char *itr_short;
+
+ printf("Usage:\n"
+ "\t%s [options] <test>\n"
+ "Options:\n", basename(progname));
+
+ for (itr = options, itr_short = options_short;
+ itr->name != NULL; itr++, itr_short++)
+ printf("\t-%c, --%s\n", *itr_short, itr->name);
+}
+
+static void test_list(const struct test *start, const struct test *stop)
+{
+ const struct test *t;
+
+ printf("Available tests:\n");
+ for (t = start; t < stop; t++)
+ printf("\t%s, %s\n", t->name, t->description);
+}
+
+int test_init(const struct test *start, const struct test *stop,
+ int argc, char *const argv[])
+{
+ progname = argv[0];
+
+ for (;;) {
+ int c, idx = 0;
+ c = getopt_long(argc, argv, options_short, options, &idx);
+ if (c == -1)
+ break;
+ switch (c) {
+ case 'l':
+ test_list(start, stop);
+ return 0;
+ case 'h':
+ help();
+ return 0;
+ case 'n':
+ oneshot = 1;
+ break;
+ case '?':
+ return -1;
+ default:
+ ERR("unexpected getopt_long() value %c\n", c);
+ return -1;
+ }
+ }
+
+ if (isatty(STDOUT_FILENO) == 0) {
+ ANSI_HIGHLIGHT_OFF = "";
+ ANSI_HIGHLIGHT_RED_ON = "";
+ ANSI_HIGHLIGHT_GREEN_ON = "";
+ }
+
+ return optind;
+}
+
+const struct test *test_find(const struct test *start,
+ const struct test *stop, const char *name)
+{
+ const struct test *t;
+
+ for (t = start; t < stop; t++) {
+ if (streq(t->name, name))
+ return t;
+ }
+
+ return NULL;
+}
+
+static int test_spawn_test(const struct test *t)
+{
+ const char *const args[] = { progname, "-n", t->name, NULL };
+
+ execv(progname, (char *const *) args);
+
+ ERR("failed to spawn %s for %s: %m\n", progname, t->name);
+ return EXIT_FAILURE;
+}
+
+static int test_run_spawned(const struct test *t)
+{
+ int err = t->func(t);
+ exit(err);
+
+ return EXIT_FAILURE;
+}
+
+int test_spawn_prog(const char *prog, const char *const args[])
+{
+ execv(prog, (char *const *) args);
+
+ ERR("failed to spawn %s\n", prog);
+ ERR("did you forget to build tools?\n");
+ return EXIT_FAILURE;
+}
+
+static void test_export_environ(const struct test *t)
+{
+ char *preload = NULL;
+ size_t preloadlen = 0;
+ size_t i;
+ const struct keyval *env;
+
+ unsetenv("LD_PRELOAD");
+
+ for (i = 0; i < _TC_LAST; i++) {
+ const char *ldpreload;
+ size_t ldpreloadlen;
+ char *tmp;
+
+ if (t->config[i] == NULL)
+ continue;
+
+ setenv(env_config[i].key, t->config[i], 1);
+
+ ldpreload = env_config[i].ldpreload;
+ ldpreloadlen = strlen(ldpreload);
+ tmp = realloc(preload, preloadlen + 2 + ldpreloadlen);
+ if (tmp == NULL) {
+ ERR("oom: test_export_environ()\n");
+ return;
+ }
+ preload = tmp;
+
+ if (preloadlen > 0)
+ preload[preloadlen++] = ' ';
+ memcpy(preload + preloadlen, ldpreload, ldpreloadlen);
+ preloadlen += ldpreloadlen;
+ preload[preloadlen] = '\0';
+ }
+
+ if (preload != NULL)
+ setenv("LD_PRELOAD", preload, 1);
+
+ free(preload);
+
+ for (env = t->env_vars; env && env->key; env++)
+ setenv(env->key, env->val, 1);
+}
+
+static inline int test_run_child(const struct test *t, int fdout[2],
+ int fderr[2], int fdmonitor[2])
+{
+ /* kill child if parent dies */
+ prctl(PR_SET_PDEATHSIG, SIGTERM);
+
+ test_export_environ(t);
+
+ /* Close read-fds and redirect std{out,err} to the write-fds */
+ if (t->output.out != NULL) {
+ close(fdout[0]);
+ if (dup2(fdout[1], STDOUT_FILENO) < 0) {
+ ERR("could not redirect stdout to pipe: %m\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (t->output.err != NULL) {
+ close(fderr[0]);
+ if (dup2(fderr[1], STDERR_FILENO) < 0) {
+ ERR("could not redirect stderr to pipe: %m\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ close(fdmonitor[0]);
+
+ if (t->config[TC_ROOTFS] != NULL) {
+ const char *stamp = TESTSUITE_ROOTFS "../stamp-rootfs";
+ const char *rootfs = t->config[TC_ROOTFS];
+ struct stat rootfsst, stampst;
+
+ if (stat(stamp, &stampst) != 0) {
+ ERR("could not stat %s\n - %m", stamp);
+ exit(EXIT_FAILURE);
+ }
+
+ if (stat(rootfs, &rootfsst) != 0) {
+ ERR("could not stat %s\n - %m", rootfs);
+ exit(EXIT_FAILURE);
+ }
+
+ if (stat_mstamp(&rootfsst) > stat_mstamp(&stampst)) {
+ ERR("rootfs %s is dirty, please run 'make rootfs' before runnning this test\n",
+ rootfs);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (t->need_spawn)
+ return test_spawn_test(t);
+ else
+ return test_run_spawned(t);
+}
+
+#define BUFSZ 4096
+
+enum fd_cmp_type {
+ FD_CMP_MONITOR,
+ FD_CMP_OUT,
+ FD_CMP_ERR,
+ FD_CMP_MAX = FD_CMP_ERR,
+};
+
+struct fd_cmp {
+ enum fd_cmp_type type;
+ int fd;
+ int fd_match;
+ bool activity;
+ const char *path;
+ const char *name;
+ char buf[BUFSZ];
+ char buf_match[BUFSZ];
+ unsigned int head;
+ unsigned int head_match;
+};
+
+static int fd_cmp_check_activity(struct fd_cmp *fd_cmp)
+{
+ struct stat st;
+
+ /* not monitoring or monitoring and it has activity */
+ if (fd_cmp == NULL || fd_cmp->fd < 0 || fd_cmp->activity)
+ return 0;
+
+ /* monitoring, there was no activity and size matches */
+ if (stat(fd_cmp->path, &st) == 0 && st.st_size == 0)
+ return 0;
+
+ ERR("Expecting output on %s, but test didn't produce any\n",
+ fd_cmp->name);
+
+ return -1;
+}
+
+static bool fd_cmp_is_active(struct fd_cmp *fd_cmp)
+{
+ return fd_cmp->fd != -1;
+}
+
+static int fd_cmp_open_monitor(struct fd_cmp *fd_cmp, int fd, int fd_ep)
+{
+ struct epoll_event ep = {};
+
+ ep.events = EPOLLHUP;
+ ep.data.ptr = fd_cmp;
+ if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd, &ep) < 0) {
+ ERR("could not add monitor fd to epoll: %m\n");
+ return -errno;
+ }
+
+ return 0;
+}
+
+static int fd_cmp_open_std(struct fd_cmp *fd_cmp,
+ const char *fn, int fd, int fd_ep)
+{
+ struct epoll_event ep = {};
+ int fd_match;
+
+ fd_match = open(fn, O_RDONLY);
+ if (fd_match < 0) {
+ ERR("could not open %s for read: %m\n", fn);
+ return -errno;
+ }
+ ep.events = EPOLLIN;
+ ep.data.ptr = fd_cmp;
+ if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd, &ep) < 0) {
+ ERR("could not add fd to epoll: %m\n");
+ close(fd_match);
+ return -errno;
+ }
+
+ return fd_match;
+}
+
+/* opens output file AND adds descriptor to epoll */
+static int fd_cmp_open(struct fd_cmp **fd_cmp_out,
+ enum fd_cmp_type type, const char *fn, int fd,
+ int fd_ep)
+{
+ int err = 0;
+ struct fd_cmp *fd_cmp;
+
+ fd_cmp = calloc(1, sizeof(*fd_cmp));
+ if (fd_cmp == NULL) {
+ ERR("could not allocate fd_cmp\n");
+ return -ENOMEM;
+ }
+
+ switch (type) {
+ case FD_CMP_MONITOR:
+ err = fd_cmp_open_monitor(fd_cmp, fd, fd_ep);
+ break;
+ case FD_CMP_OUT:
+ fd_cmp->name = "STDOUT";
+ err = fd_cmp_open_std(fd_cmp, fn, fd, fd_ep);
+ break;
+ case FD_CMP_ERR:
+ fd_cmp->name = "STDERR";
+ err = fd_cmp_open_std(fd_cmp, fn, fd, fd_ep);
+ break;
+ default:
+ ERR("unknown fd type %d\n", type);
+ err = -1;
+ }
+
+ if (err < 0) {
+ free(fd_cmp);
+ return err;
+ }
+
+ fd_cmp->fd_match = err;
+ fd_cmp->fd = fd;
+ fd_cmp->type = type;
+ fd_cmp->path = fn;
+
+ *fd_cmp_out = fd_cmp;
+ return 0;
+}
+
+static int fd_cmp_check_ev_in(struct fd_cmp *fd_cmp)
+{
+ if (fd_cmp->type == FD_CMP_MONITOR) {
+ ERR("Unexpected activity on monitor pipe\n");
+ return -EINVAL;
+ }
+ fd_cmp->activity = true;
+
+ return 0;
+}
+
+static void fd_cmp_delete_ep(struct fd_cmp *fd_cmp, int fd_ep)
+{
+ if (epoll_ctl(fd_ep, EPOLL_CTL_DEL, fd_cmp->fd, NULL) < 0) {
+ ERR("could not remove fd %d from epoll: %m\n", fd_cmp->fd);
+ }
+ fd_cmp->fd = -1;
+}
+
+static void fd_cmp_close(struct fd_cmp *fd_cmp)
+{
+ if (fd_cmp == NULL)
+ return;
+
+ if (fd_cmp->fd >= 0)
+ close(fd_cmp->fd);
+ free(fd_cmp);
+}
+
+static bool fd_cmp_regex_one(const char *pattern, const char *s)
+{
+ _cleanup_(regfree) regex_t re = { };
+
+ return !regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) &&
+ !regexec(&re, s, 0, NULL, 0);
+}
+
+/*
+ * read fd and fd_match, checking the first matches the regex of the second,
+ * line by line
+ */
+static bool fd_cmp_regex(struct fd_cmp *fd_cmp, const struct test *t)
+{
+ char *p, *p_match;
+ int done = 0, done_match = 0, r;
+
+ if (fd_cmp->head >= sizeof(fd_cmp->buf)) {
+ ERR("Read %zu bytes without a newline\n", sizeof(fd_cmp->buf));
+ ERR("output: %.*s", (int)sizeof(fd_cmp->buf), fd_cmp->buf);
+ return false;
+ }
+
+ r = read(fd_cmp->fd, fd_cmp->buf + fd_cmp->head,
+ sizeof(fd_cmp->buf) - fd_cmp->head);
+ if (r <= 0)
+ return true;
+
+ fd_cmp->head += r;
+
+ /*
+ * Process as many lines as read from fd and that fits in the buffer -
+ * it's assumed that if we get N lines from fd, we should be able to
+ * get the same amount from fd_match
+ */
+ for (;;) {
+ p = memchr(fd_cmp->buf + done, '\n', fd_cmp->head - done);
+ if (!p)
+ break;
+ *p = '\0';
+
+ p_match = memchr(fd_cmp->buf_match + done_match, '\n',
+ fd_cmp->head_match - done_match);
+ if (!p_match) {
+ if (fd_cmp->head_match >= sizeof(fd_cmp->buf_match)) {
+ ERR("Read %zu bytes without a match\n", sizeof(fd_cmp->buf_match));
+ ERR("output: %.*s", (int)sizeof(fd_cmp->buf_match), fd_cmp->buf_match);
+ return false;
+ }
+
+ /* pump more data from file */
+ r = read(fd_cmp->fd_match, fd_cmp->buf_match + fd_cmp->head_match,
+ sizeof(fd_cmp->buf_match) - fd_cmp->head_match);
+ if (r <= 0) {
+ ERR("could not read match fd %d\n", fd_cmp->fd_match);
+ return false;
+ }
+ fd_cmp->head_match += r;
+ p_match = memchr(fd_cmp->buf_match + done_match, '\n',
+ fd_cmp->head_match - done_match);
+ if (!p_match) {
+ ERR("could not find match line from fd %d\n", fd_cmp->fd_match);
+ return false;
+ }
+ }
+ *p_match = '\0';
+
+ if (!fd_cmp_regex_one(fd_cmp->buf_match + done_match, fd_cmp->buf + done)) {
+ ERR("Output does not match pattern on %s:\n", fd_cmp->name);
+ ERR("pattern: %s\n", fd_cmp->buf_match + done_match);
+ ERR("output : %s\n", fd_cmp->buf + done);
+ return false;
+ }
+
+ done = p - fd_cmp->buf + 1;
+ done_match = p_match - fd_cmp->buf_match + 1;
+ }
+
+ /*
+ * Prepare for the next call: anything we processed we remove from the
+ * buffer by memmoving the remaining bytes up to the beginning
+ */
+ if (done) {
+ if (fd_cmp->head - done)
+ memmove(fd_cmp->buf, fd_cmp->buf + done, fd_cmp->head - done);
+ fd_cmp->head -= done;
+ }
+
+ if (done_match) {
+ if (fd_cmp->head_match - done_match)
+ memmove(fd_cmp->buf_match, fd_cmp->buf_match + done_match,
+ fd_cmp->head_match - done_match);
+ fd_cmp->head_match -= done_match;
+ }
+
+ return true;
+}
+
+/* read fd and fd_match, checking they match exactly */
+static bool fd_cmp_exact(struct fd_cmp *fd_cmp, const struct test *t)
+{
+ int r, rmatch, done = 0;
+
+ r = read(fd_cmp->fd, fd_cmp->buf, sizeof(fd_cmp->buf) - 1);
+ if (r <= 0)
+ /* try again later */
+ return true;
+
+ /* read as much data from fd_match as we read from fd */
+ for (;;) {
+ rmatch = read(fd_cmp->fd_match, fd_cmp->buf_match + done, r - done);
+ if (rmatch == 0)
+ break;
+
+ if (rmatch < 0) {
+ if (errno == EINTR)
+ continue;
+ ERR("could not read match fd %d\n", fd_cmp->fd_match);
+ return false;
+ }
+
+ done += rmatch;
+ }
+
+ fd_cmp->buf[r] = '\0';
+ fd_cmp->buf_match[r] = '\0';
+
+ if (t->print_outputs)
+ printf("%s: %s\n", fd_cmp->name, fd_cmp->buf);
+
+ if (!streq(fd_cmp->buf, fd_cmp->buf_match)) {
+ ERR("Outputs do not match on %s:\n", fd_cmp->name);
+ ERR("correct:\n%s\n", fd_cmp->buf_match);
+ ERR("wrong:\n%s\n", fd_cmp->buf);
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_run_parent_check_outputs(const struct test *t,
+ int fdout, int fderr, int fdmonitor,
+ pid_t child)
+{
+ int err, fd_ep;
+ unsigned long long end_usec, start_usec;
+ struct fd_cmp *fd_cmp_out = NULL;
+ struct fd_cmp *fd_cmp_err = NULL;
+ struct fd_cmp *fd_cmp_monitor = NULL;
+ int n_fd = 0;
+
+ fd_ep = epoll_create1(EPOLL_CLOEXEC);
+ if (fd_ep < 0) {
+ ERR("could not create epoll fd: %m\n");
+ return false;
+ }
+
+ if (t->output.out != NULL) {
+ err = fd_cmp_open(&fd_cmp_out,
+ FD_CMP_OUT, t->output.out, fdout, fd_ep);
+ if (err < 0)
+ goto out;
+ n_fd++;
+ }
+
+ if (t->output.err != NULL) {
+ err = fd_cmp_open(&fd_cmp_err,
+ FD_CMP_ERR, t->output.err, fderr, fd_ep);
+ if (err < 0)
+ goto out;
+ n_fd++;
+ }
+
+ err = fd_cmp_open(&fd_cmp_monitor, FD_CMP_MONITOR, NULL, fdmonitor, fd_ep);
+ if (err < 0)
+ goto out;
+ n_fd++;
+
+ start_usec = now_usec();
+ end_usec = start_usec + TEST_TIMEOUT_USEC;
+
+ for (err = 0; n_fd > 0;) {
+ int fdcount, i, timeout;
+ struct epoll_event ev[4];
+ unsigned long long curr_usec = now_usec();
+
+ if (curr_usec > end_usec)
+ break;
+
+ timeout = (end_usec - curr_usec) / USEC_PER_MSEC;
+ fdcount = epoll_wait(fd_ep, ev, 4, timeout);
+ if (fdcount < 0) {
+ if (errno == EINTR)
+ continue;
+ err = -errno;
+ ERR("could not poll: %m\n");
+ goto out;
+ }
+
+ for (i = 0; i < fdcount; i++) {
+ struct fd_cmp *fd_cmp = ev[i].data.ptr;
+ bool ret;
+
+ if (ev[i].events & EPOLLIN) {
+ err = fd_cmp_check_ev_in(fd_cmp);
+ if (err < 0)
+ goto out;
+
+ if (t->output.regex)
+ ret = fd_cmp_regex(fd_cmp, t);
+ else
+ ret = fd_cmp_exact(fd_cmp, t);
+
+ if (!ret) {
+ err = -1;
+ goto out;
+ }
+ } else if (ev[i].events & EPOLLHUP) {
+ fd_cmp_delete_ep(fd_cmp, fd_ep);
+ n_fd--;
+ }
+ }
+ }
+
+ err = fd_cmp_check_activity(fd_cmp_out);
+ err |= fd_cmp_check_activity(fd_cmp_err);
+
+ if (err == 0 && fd_cmp_is_active(fd_cmp_monitor)) {
+ err = -EINVAL;
+ ERR("Test '%s' timed out, killing %d\n", t->name, child);
+ kill(child, SIGKILL);
+ }
+
+out:
+ fd_cmp_close(fd_cmp_out);
+ fd_cmp_close(fd_cmp_err);
+ fd_cmp_close(fd_cmp_monitor);
+ close(fd_ep);
+
+ return err == 0;
+}
+
+static inline int safe_read(int fd, void *buf, size_t count)
+{
+ int r;
+
+ while (1) {
+ r = read(fd, buf, count);
+ if (r == -1 && errno == EINTR)
+ continue;
+ break;
+ }
+
+ return r;
+}
+
+static bool check_generated_files(const struct test *t)
+{
+ const struct keyval *k;
+
+ /* This is not meant to be a diff replacement, just stupidly check if
+ * the files match. Bear in mind they can be binary files */
+ for (k = t->output.files; k && k->key; k++) {
+ struct stat sta, stb;
+ int fda = -1, fdb = -1;
+ char bufa[4096];
+ char bufb[4096];
+
+ fda = open(k->key, O_RDONLY);
+ if (fda < 0) {
+ ERR("could not open %s\n - %m\n", k->key);
+ goto fail;
+ }
+
+ fdb = open(k->val, O_RDONLY);
+ if (fdb < 0) {
+ ERR("could not open %s\n - %m\n", k->val);
+ goto fail;
+ }
+
+ if (fstat(fda, &sta) != 0) {
+ ERR("could not fstat %d %s\n - %m\n", fda, k->key);
+ goto fail;
+ }
+
+ if (fstat(fdb, &stb) != 0) {
+ ERR("could not fstat %d %s\n - %m\n", fdb, k->key);
+ goto fail;
+ }
+
+ if (sta.st_size != stb.st_size) {
+ ERR("sizes do not match %s %s\n", k->key, k->val);
+ goto fail;
+ }
+
+ for (;;) {
+ int r, done;
+
+ r = safe_read(fda, bufa, sizeof(bufa));
+ if (r < 0)
+ goto fail;
+
+ if (r == 0)
+ /* size is already checked, go to next file */
+ goto next;
+
+ for (done = 0; done < r;) {
+ int r2 = safe_read(fdb, bufb + done, r - done);
+
+ if (r2 <= 0)
+ goto fail;
+
+ done += r2;
+ }
+
+ if (memcmp(bufa, bufb, r) != 0)
+ goto fail;
+ }
+
+next:
+ close(fda);
+ close(fdb);
+ continue;
+
+fail:
+ if (fda >= 0)
+ close(fda);
+ if (fdb >= 0)
+ close(fdb);
+
+ return false;
+ }
+
+ return true;
+}
+
+static int cmp_modnames(const void *m1, const void *m2)
+{
+ const char *s1 = *(char *const *)m1;
+ const char *s2 = *(char *const *)m2;
+ int i;
+
+ for (i = 0; s1[i] || s2[i]; i++) {
+ char c1 = s1[i], c2 = s2[i];
+ if (c1 == '-')
+ c1 = '_';
+ if (c2 == '-')
+ c2 = '_';
+ if (c1 != c2)
+ return c1 - c2;
+ }
+ return 0;
+}
+
+/*
+ * Store the expected module names in buf and return a list of pointers to
+ * them.
+ */
+static const char **read_expected_modules(const struct test *t,
+ char **buf, int *count)
+{
+ const char **res;
+ int len;
+ int i;
+ char *p;
+
+ if (t->modules_loaded[0] == '\0') {
+ *count = 0;
+ *buf = NULL;
+ return NULL;
+ }
+ *buf = strdup(t->modules_loaded);
+ if (!*buf) {
+ *count = -1;
+ return NULL;
+ }
+ len = 1;
+ for (p = *buf; *p; p++)
+ if (*p == ',')
+ len++;
+ res = malloc(sizeof(char *) * len);
+ if (!res) {
+ perror("malloc");
+ *count = -1;
+ free(*buf);
+ *buf = NULL;
+ return NULL;
+ }
+ i = 0;
+ res[i++] = *buf;
+ for (p = *buf; i < len; p++)
+ if (*p == ',') {
+ *p = '\0';
+ res[i++] = p + 1;
+ }
+ *count = len;
+ return res;
+}
+
+static char **read_loaded_modules(const struct test *t, char **buf, int *count)
+{
+ char dirname[PATH_MAX];
+ DIR *dir;
+ struct dirent *dirent;
+ int i;
+ int len = 0, bufsz;
+ char **res = NULL;
+ char *p;
+ const char *rootfs = t->config[TC_ROOTFS] ? t->config[TC_ROOTFS] : "";
+
+ /* Store the entries in /sys/module to res */
+ if (snprintf(dirname, sizeof(dirname), "%s/sys/module", rootfs)
+ >= (int)sizeof(dirname)) {
+ ERR("rootfs path too long: %s\n", rootfs);
+ *buf = NULL;
+ len = -1;
+ goto out;
+ }
+ dir = opendir(dirname);
+ /* not an error, simply return empty list */
+ if (!dir) {
+ *buf = NULL;
+ goto out;
+ }
+ bufsz = 0;
+ while ((dirent = readdir(dir))) {
+ if (dirent->d_name[0] == '.')
+ continue;
+ len++;
+ bufsz += strlen(dirent->d_name) + 1;
+ }
+ res = malloc(sizeof(char *) * len);
+ if (!res) {
+ perror("malloc");
+ len = -1;
+ goto out_dir;
+ }
+ *buf = malloc(bufsz);
+ if (!*buf) {
+ perror("malloc");
+ free(res);
+ res = NULL;
+ len = -1;
+ goto out_dir;
+ }
+ rewinddir(dir);
+ i = 0;
+ p = *buf;
+ while ((dirent = readdir(dir))) {
+ int size;
+
+ if (dirent->d_name[0] == '.')
+ continue;
+ size = strlen(dirent->d_name) + 1;
+ memcpy(p, dirent->d_name, size);
+ res[i++] = p;
+ p += size;
+ }
+out_dir:
+ closedir(dir);
+out:
+ *count = len;
+ return res;
+}
+
+static int check_loaded_modules(const struct test *t)
+{
+ int l1, l2, i1, i2;
+ const char **a1;
+ char **a2;
+ char *buf1, *buf2;
+ int err = false;
+
+ a1 = read_expected_modules(t, &buf1, &l1);
+ if (l1 < 0)
+ return err;
+ a2 = read_loaded_modules(t, &buf2, &l2);
+ if (l2 < 0)
+ goto out_a1;
+ qsort(a1, l1, sizeof(char *), cmp_modnames);
+ qsort(a2, l2, sizeof(char *), cmp_modnames);
+ i1 = i2 = 0;
+ err = true;
+ while (i1 < l1 || i2 < l2) {
+ int cmp;
+
+ if (i1 >= l1)
+ cmp = 1;
+ else if (i2 >= l2)
+ cmp = -1;
+ else
+ cmp = cmp_modnames(&a1[i1], &a2[i2]);
+ if (cmp == 0) {
+ i1++;
+ i2++;
+ } else if (cmp < 0) {
+ err = false;
+ ERR("module %s not loaded\n", a1[i1]);
+ i1++;
+ } else {
+ err = false;
+ ERR("module %s is loaded but should not be \n", a2[i2]);
+ i2++;
+ }
+ }
+ free(a2);
+ free(buf2);
+out_a1:
+ free(a1);
+ free(buf1);
+ return err;
+}
+
+static inline int test_run_parent(const struct test *t, int fdout[2],
+ int fderr[2], int fdmonitor[2], pid_t child)
+{
+ pid_t pid;
+ int err;
+ bool matchout, match_modules;
+
+ if (t->skip) {
+ LOG("%sSKIPPED%s: %s\n",
+ ANSI_HIGHLIGHT_YELLOW_ON, ANSI_HIGHLIGHT_OFF,
+ t->name);
+ err = EXIT_SUCCESS;
+ goto exit;
+ }
+
+ /* Close write-fds */
+ if (t->output.out != NULL)
+ close(fdout[1]);
+ if (t->output.err != NULL)
+ close(fderr[1]);
+ close(fdmonitor[1]);
+
+ matchout = test_run_parent_check_outputs(t, fdout[0], fderr[0],
+ fdmonitor[0], child);
+
+ /*
+ * break pipe on the other end: either child already closed or we want
+ * to stop it
+ */
+ if (t->output.out != NULL)
+ close(fdout[0]);
+ if (t->output.err != NULL)
+ close(fderr[0]);
+ close(fdmonitor[0]);
+
+ do {
+ pid = wait(&err);
+ if (pid == -1) {
+ ERR("error waitpid(): %m\n");
+ err = EXIT_FAILURE;
+ goto exit;
+ }
+ } while (!WIFEXITED(err) && !WIFSIGNALED(err));
+
+ if (WIFEXITED(err)) {
+ if (WEXITSTATUS(err) != 0)
+ ERR("'%s' [%u] exited with return code %d\n",
+ t->name, pid, WEXITSTATUS(err));
+ else
+ LOG("'%s' [%u] exited with return code %d\n",
+ t->name, pid, WEXITSTATUS(err));
+ } else if (WIFSIGNALED(err)) {
+ ERR("'%s' [%u] terminated by signal %d (%s)\n", t->name, pid,
+ WTERMSIG(err), strsignal(WTERMSIG(err)));
+ err = t->expected_fail ? EXIT_SUCCESS : EXIT_FAILURE;
+ goto exit;
+ }
+
+ if (matchout)
+ matchout = check_generated_files(t);
+ if (t->modules_loaded)
+ match_modules = check_loaded_modules(t);
+ else
+ match_modules = true;
+
+ if (t->expected_fail == false) {
+ if (err == 0) {
+ if (matchout && match_modules)
+ LOG("%sPASSED%s: %s\n",
+ ANSI_HIGHLIGHT_GREEN_ON, ANSI_HIGHLIGHT_OFF,
+ t->name);
+ else {
+ ERR("%sFAILED%s: exit ok but %s do not match: %s\n",
+ ANSI_HIGHLIGHT_RED_ON, ANSI_HIGHLIGHT_OFF,
+ matchout ? "loaded modules" : "outputs",
+ t->name);
+ err = EXIT_FAILURE;
+ }
+ } else {
+ ERR("%sFAILED%s: %s\n",
+ ANSI_HIGHLIGHT_RED_ON, ANSI_HIGHLIGHT_OFF,
+ t->name);
+ }
+ } else {
+ if (err == 0) {
+ if (matchout) {
+ ERR("%sUNEXPECTED PASS%s: exit with 0: %s\n",
+ ANSI_HIGHLIGHT_RED_ON, ANSI_HIGHLIGHT_OFF,
+ t->name);
+ err = EXIT_FAILURE;
+ } else {
+ ERR("%sUNEXPECTED PASS%s: exit with 0 and outputs do not match: %s\n",
+ ANSI_HIGHLIGHT_RED_ON, ANSI_HIGHLIGHT_OFF,
+ t->name);
+ err = EXIT_FAILURE;
+ }
+ } else {
+ if (matchout) {
+ LOG("%sEXPECTED FAIL%s: %s\n",
+ ANSI_HIGHLIGHT_GREEN_ON, ANSI_HIGHLIGHT_OFF,
+ t->name);
+ err = EXIT_SUCCESS;
+ } else {
+ LOG("%sEXPECTED FAIL%s: exit with %d but outputs do not match: %s\n",
+ ANSI_HIGHLIGHT_GREEN_ON, ANSI_HIGHLIGHT_OFF,
+ WEXITSTATUS(err), t->name);
+ err = EXIT_FAILURE;
+ }
+ }
+ }
+
+exit:
+ LOG("------\n");
+ return err;
+}
+
+static int prepend_path(const char *extra)
+{
+ char *oldpath, *newpath;
+ int r;
+
+ if (extra == NULL)
+ return 0;
+
+ oldpath = getenv("PATH");
+ if (oldpath == NULL)
+ return setenv("PATH", extra, 1);
+
+ if (asprintf(&newpath, "%s:%s", extra, oldpath) < 0) {
+ ERR("failed to allocate memory to new PATH\n");
+ return -1;
+ }
+
+ r = setenv("PATH", newpath, 1);
+ free(newpath);
+
+ return r;
+}
+
+int test_run(const struct test *t)
+{
+ pid_t pid;
+ int fdout[2];
+ int fderr[2];
+ int fdmonitor[2];
+
+ if (t->need_spawn && oneshot)
+ test_run_spawned(t);
+
+ if (t->output.out != NULL) {
+ if (pipe(fdout) != 0) {
+ ERR("could not create out pipe for %s\n", t->name);
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (t->output.err != NULL) {
+ if (pipe(fderr) != 0) {
+ ERR("could not create err pipe for %s\n", t->name);
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (pipe(fdmonitor) != 0) {
+ ERR("could not create monitor pipe for %s\n", t->name);
+ return EXIT_FAILURE;
+ }
+
+ if (prepend_path(t->path) < 0) {
+ ERR("failed to prepend '%s' to PATH\n", t->path);
+ return EXIT_FAILURE;
+ }
+
+ LOG("running %s, in forked context\n", t->name);
+
+ pid = fork();
+ if (pid < 0) {
+ ERR("could not fork(): %m\n");
+ LOG("FAILED: %s\n", t->name);
+ return EXIT_FAILURE;
+ }
+
+ if (pid > 0)
+ return test_run_parent(t, fdout, fderr, fdmonitor, pid);
+
+ return test_run_child(t, fdout, fderr, fdmonitor);
+}
diff --git a/testsuite/testsuite.h b/testsuite/testsuite.h
new file mode 100644
index 0000000..44d1730
--- /dev/null
+++ b/testsuite/testsuite.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2012-2013 ProFUSION embedded systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <shared/macro.h>
+
+struct test;
+typedef int (*testfunc)(const struct test *t);
+
+enum test_config {
+ /*
+ * Where's the roots dir for this test. It will LD_PRELOAD path.so in
+ * order to trap calls to functions using paths.
+ */
+ TC_ROOTFS = 0,
+
+ /*
+ * What's the desired string to be returned by `uname -r`. It will
+ * trap calls to uname(3P) by LD_PRELOAD'ing uname.so and then filling
+ * in the information in u.release.
+ */
+ TC_UNAME_R,
+
+ /*
+ * Fake calls to init_module(2), returning return-code and setting
+ * errno to err-code. Set this variable with the following format:
+ *
+ * modname:return-code:err-code
+ *
+ * When this variable is used, all calls to init_module() are trapped
+ * and by default the return code is 0. In other words, they fake
+ * "success" for all modules, except the ones in the list above, for
+ * which the return codes are used.
+ */
+ TC_INIT_MODULE_RETCODES,
+
+ /*
+ * Fake calls to delete_module(2), returning return-code and setting
+ * errno to err-code. Set this variable with the following format:
+ *
+ * modname:return-code:err-code
+ *
+ * When this variable is used, all calls to init_module() are trapped
+ * and by default the return code is 0. In other words, they fake
+ * "success" for all modules, except the ones in the list above, for
+ * which the return codes are used.
+ */
+ TC_DELETE_MODULE_RETCODES,
+
+ _TC_LAST,
+};
+
+#define S_TC_ROOTFS "TESTSUITE_ROOTFS"
+#define S_TC_UNAME_R "TESTSUITE_UNAME_R"
+#define S_TC_INIT_MODULE_RETCODES "TESTSUITE_INIT_MODULE_RETCODES"
+#define S_TC_DELETE_MODULE_RETCODES "TESTSUITE_DELETE_MODULE_RETCODES"
+
+struct keyval {
+ const char *key;
+ const char *val;
+};
+
+struct test {
+ const char *name;
+ const char *description;
+ struct {
+ /* File with correct stdout */
+ const char *out;
+ /* File with correct stderr */
+ const char *err;
+
+ /*
+ * whether to treat the correct files as regex to the real
+ * output
+ */
+ bool regex;
+
+ /*
+ * Vector with pair of files
+ * key = correct file
+ * val = file to check
+ */
+ const struct keyval *files;
+ } output;
+ /* comma-separated list of loaded modules at the end of the test */
+ const char *modules_loaded;
+ testfunc func;
+ const char *config[_TC_LAST];
+ const char *path;
+ const struct keyval *env_vars;
+ bool need_spawn;
+ bool expected_fail;
+ /* allow to skip tests that don't meet compile-time dependencies */
+ bool skip;
+ bool print_outputs;
+} __attribute__((aligned(8)));
+
+
+int test_init(const struct test *start, const struct test *stop,
+ int argc, char *const argv[]);
+const struct test *test_find(const struct test *start, const struct test *stop,
+ const char *name);
+int test_spawn_prog(const char *prog, const char *const args[]);
+int test_run(const struct test *t);
+
+#define TS_EXPORT __attribute__ ((visibility("default")))
+
+#define _LOG(prefix, fmt, ...) printf("TESTSUITE: " prefix fmt, ## __VA_ARGS__)
+#define LOG(fmt, ...) _LOG("", fmt, ## __VA_ARGS__)
+#define WARN(fmt, ...) _LOG("WARN: ", fmt, ## __VA_ARGS__)
+#define ERR(fmt, ...) _LOG("ERR: ", fmt, ## __VA_ARGS__)
+
+#define assert_return(expr, r) \
+ do { \
+ if ((!(expr))) { \
+ ERR("Failed assertion: " #expr " %s:%d %s\n", \
+ __FILE__, __LINE__, __PRETTY_FUNCTION__); \
+ return (r); \
+ } \
+ } while (false)
+
+
+/* Test definitions */
+#define DEFINE_TEST_WITH_FUNC(_name, _func, ...) \
+ static const struct test UNIQ(s##_name) \
+ __attribute__((used, section("kmod_tests"), aligned(8))) = { \
+ .name = #_name, \
+ .func = _func, \
+ ## __VA_ARGS__ \
+ };
+
+#define DEFINE_TEST(_name, ...) DEFINE_TEST_WITH_FUNC(_name, _name, __VA_ARGS__)
+
+#define TESTSUITE_MAIN() \
+ extern struct test __start_kmod_tests[] __attribute__((weak, visibility("hidden"))); \
+ extern struct test __stop_kmod_tests[] __attribute__((weak, visibility("hidden"))); \
+ int main(int argc, char *argv[]) \
+ { \
+ const struct test *t; \
+ int arg; \
+ \
+ arg = test_init(__start_kmod_tests, __stop_kmod_tests, argc, argv); \
+ if (arg == 0) \
+ return 0; \
+ if (arg < 0) \
+ return EXIT_FAILURE; \
+ \
+ if (arg < argc) { \
+ t = test_find(__start_kmod_tests, __stop_kmod_tests, argv[arg]); \
+ if (t == NULL) { \
+ fprintf(stderr, "could not find test %s\n", argv[arg]); \
+ exit(EXIT_FAILURE); \
+ } \
+ \
+ return test_run(t); \
+ } \
+ \
+ for (t = __start_kmod_tests; t < __stop_kmod_tests; t++) { \
+ if (test_run(t) != 0) \
+ exit(EXIT_FAILURE); \
+ } \
+ \
+ exit(EXIT_SUCCESS); \
+ } \
+
+#ifdef noreturn
+# define __noreturn noreturn
+#elif __STDC_VERSION__ >= 201112L
+# define __noreturn _Noreturn
+#else
+# define __noreturn __attribute__((noreturn))
+#endif
diff --git a/testsuite/uname.c b/testsuite/uname.c
new file mode 100644
index 0000000..27f92d5
--- /dev/null
+++ b/testsuite/uname.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2012-2013 ProFUSION embedded systems
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+
+#include "testsuite.h"
+
+TS_EXPORT int uname(struct utsname *u)
+{
+ static void *nextlib = NULL;
+ static int (*nextlib_uname)(struct utsname *u);
+ const char *release;
+ int err;
+ size_t sz;
+
+ if (nextlib == NULL) {
+#ifdef RTLD_NEXT
+ nextlib = RTLD_NEXT;
+#else
+ nextlib = dlopen("libc.so.6", RTLD_LAZY);
+#endif
+ nextlib_uname = dlsym(nextlib, "uname");
+ }
+
+ err = nextlib_uname(u);
+ if (err < 0)
+ return err;
+
+ if (!environ)
+ /*
+ * probably called from within glibc before main(); unsafe
+ * to call getenv()
+ */
+ return 0;
+
+ release = getenv(S_TC_UNAME_R);
+ if (release == NULL) {
+ fprintf(stderr, "TRAP uname(): missing export %s?\n",
+ S_TC_UNAME_R);
+ return 0;
+ }
+
+ sz = strlen(release) + 1;
+ if (sz > sizeof(u->release)) {
+ fprintf(stderr, "uname(): sizeof release (%s) "
+ "is greater than available space: %zu",
+ release, sizeof(u->release));
+ errno = -EFAULT;
+ return -1;
+ }
+
+ memcpy(u->release, release, sz);
+ return 0;
+}